git.iko.soy/rowtype-yoga/purescript-docs-search
on master help sign in
54 files changed+4712−1710
since splitsnapshots
unifiedsplit
.github/workflows/build.yml+44 .github/workflows/release.yml+55 .travis.yml−51 CHANGELOG.md+49 README.md+4−4 ci-npmrc.txt+4 package-lock.json+2285 package.json+23−20 packages.dhall+114−26 release.sh+24 spago.dhall+53−41 src/Docs/Search/App.purs+54−39 src/Docs/Search/App/SearchField.purs+11−10 src/Docs/Search/App/SearchResults.purs+86−84 src/Docs/Search/App/Sidebar.purs+79−31 src/Docs/Search/BrowserEngine.js+1−1 src/Docs/Search/BrowserEngine.purs+10−14 src/Docs/Search/Config.purs+79−66 src/Docs/Search/Declarations.purs+77−48 src/Docs/Search/DocsJson.purs+15−10 src/Docs/Search/Engine.purs+27−10 src/Docs/Search/IndexBuilder.js+4−5 src/Docs/Search/IndexBuilder.purs+70−25 src/Docs/Search/Interactive.purs+103−61 src/Docs/Search/Loader.js+26 src/Docs/Search/Loader.purs+38 src/Docs/Search/Main.purs+45−34 src/Docs/Search/Meta.purs+21 src/Docs/Search/ModuleIndex.js+1−1 src/Docs/Search/ModuleIndex.purs+36−29 src/Docs/Search/ModuleParser.purs+50 src/Docs/Search/PackageIndex.js−24 src/Docs/Search/PackageIndex.purs+24−31 src/Docs/Search/Score.purs+20−15 src/Docs/Search/SearchResult.purs+12−10 src/Docs/Search/TypeDecoder.purs+46−78 src/Docs/Search/TypeIndex.js+1−1 src/Docs/Search/TypeIndex.purs+11−10 src/Docs/Search/TypePrinter.purs+19−21 src/Docs/Search/TypeQuery.purs+65−51 src/Docs/Search/TypeShape.js+1−1 src/Docs/Search/TypeShape.purs+10−4 src/Docs/Search/Types.purs+101−2 src/Docs/Search/URIHash.js+1−1 src/Docs/Search/URIHash.purs+3−3 test/Main.purs+14−558 test/Test/Declarations.purs+18−16 test/Test/Extra.purs+6−5 test/Test/IndexBuilder.purs+9−9 test/Test/ModuleIndex.purs+9−10 test/Test/ModuleParser.purs+61 test/Test/TypeJson.purs+300 test/Test/TypeQuery.purs+425−250 test/Test/UI.purs+68
.github/workflows/build.ymlnew file+44
@@ -0,0 +1,44 @@
1+name: build
2+on:
3+ push:
4+ branches: [master]
5+ pull_request:
6+ branches: [master]
7+jobs:
8+ build:
9+ runs-on: ubuntu-latest
10+ steps:
11+ - uses: actions/checkout@v2
12+
13+ - uses: actions/setup-node@v2
14+ with:
15+ node-version: "18"
16+
17+ - uses: purescript-contrib/setup-purescript@main
18+
19+ - uses: actions/cache@v2
20+ with:
21+ path: ~/.npm
22+ key: ${{ runner.os }}-node-${{ hashFiles('./**/package-lock.json') }}
23+ restore-keys: |
24+ ${{ runner.os }}-node-
25+
26+ - name: Cache PureScript dependencies
27+ uses: actions/cache@v2
28+ with:
29+ key: ${{ runner.os }}-spago-${{ hashFiles('./**/*.dhall') }}
30+ path: |
31+ .spago
32+ output
33+
34+ - name: Install
35+ run: |
36+ npm ci
37+ spago install
38+
39+ - name: Build
40+ run: |
41+ npm run build
42+ npm test
43+ spago docs --no-search
44+ ./dist/purescript-docs-search.cjs build-index
.github/workflows/release.ymlnew file+55
@@ -0,0 +1,55 @@
1+name: release
2+on:
3+ push:
4+ tags:
5+ - 'v*.*.*'
6+jobs:
7+ release:
8+ runs-on: ubuntu-latest
9+ steps:
10+ - uses: actions/checkout@v2
11+
12+ - uses: actions/setup-node@v2
13+ with:
14+ node-version: "18"
15+
16+ - uses: purescript-contrib/setup-purescript@main
17+
18+ - uses: actions/cache@v2
19+ with:
20+ path: ~/.npm
21+ key: ${{ runner.os }}-node-${{ hashFiles('./**/package-lock.json') }}
22+ restore-keys: |
23+ ${{ runner.os }}-node-
24+
25+ - name: Cache PureScript dependencies
26+ uses: actions/cache@v2
27+ with:
28+ key: ${{ runner.os }}-spago-${{ hashFiles('./**/*.dhall') }}
29+ path: |
30+ .spago
31+ output
32+
33+ - name: Build
34+ run: |
35+ npm ci
36+ spago install
37+ npm run build
38+
39+ - name: Release
40+ uses: softprops/action-gh-release@v1
41+ with:
42+ files: |
43+ dist/docs-search-app.js
44+ dist/purescript-docs-search.cjs
45+ env:
46+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47+
48+ - name: Publish to NPM
49+ shell: bash
50+ env:
51+ NODE_AUTH_TOKEN: ${{ secrets.NPM_API_TOKEN }}
52+ run: |
53+ mv ci-npmrc.txt .npmrc
54+ npm ci
55+ npm publish --non-interactive --access public
.travis.ymldeleted−51
@@ -1,51 +0,0 @@
1−language: node_js
2−dist: trusty
3−sudo: required
4−node_js: stable
5−
6−# Build only master and release tags
7−branches:
8− only:
9− - master
10− - /^v\d+\.\d+\.\d+(\.\d+)?$/
11−
12−env:
13− matrix:
14− - PATH=$HOME/purescript:$PATH
15−
16−install:
17−- export PURS_VERSION=v0.13.3
18−- wget -O $HOME/purescript.tar.gz https://github.com/purescript/purescript/releases/download/$PURS_VERSION/linux64.tar.gz
19−- tar -xvf $HOME/purescript.tar.gz -C $HOME/
20−- chmod a+x $HOME/purescript
21−- npm install -g spago
22−- npm install
23−- spago install
24−
25−script:
26−- npm run build
27−- npm test
28−# Check if it the app is able to build the search index for itself.
29−- spago docs
30−- ./dist/purescript-docs-search build-index
31−
32−deploy:
33− - provider: releases
34− api_key: $API_KEY
35− file:
36− - dist/docs-search-app.js
37− - dist/purescript-docs-search
38− skip_cleanup: true
39− on:
40− tags: true
41− script:
42− - echo 'done'
43− - provider: npm
44− api_token:
45− secure: $NPM_API_TOKEN
46− email: klntsky@gmail.com
47− skip_cleanup: true
48− edge: true
49− on:
50− tags: true
51− branch: master
CHANGELOG.md+49
@@ -5,6 +5,55 @@ All notable changes to this project will be documented in this file.
55The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77
8+## [0.0.12 - 2022-08-31]
9+
10+Changes:
11+- Package structure change: `dist/purescript-docs-search.cjs` has been moved to `dist/purescript-docs-search.cjs` due to NodeJS restrictions for `type: module` packages.
12+- Improve output for data and newtype constuctors ([#58](https://github.com/purescript/purescript-docs-search/pull/58))
13+
14+New features:
15+- Docs for each CLI option
16+- New `--source-files` option that allows to specify `.purs` sources (see below)
17+
18+Bugfixes:
19+- Include modules with only re-exports in the module list ([#62](https://github.com/purescript/purescript-docs-search/issues/62))
20+- Fix `docs.json` parser for some types
21+
22+## [0.0.11 - 2021-04-15]
23+
24+Changes:
25+- Adapt JSON API for use with PureScript v0.14.
26+
27+## [0.0.10 - 2020-08-11]
28+
29+New features:
30+- Add `--package-name` flag to allow passing local package name.
31+
32+Changes:
33+- Group modules by default.
34+- Add local package modules and `Prim*` modules to the sidebar.
35+- UI tests, using [purescript-toppokki](https://github.com/justinwoo/purescript-toppokki/).
36+
37+## [0.0.9 - 2020-07-29]
38+
39+New features:
40+- Implement sorting by package popularity for declarations.
41+- Add app version info to the footer.
42+- Scroll to document top when search bar gets focus.
43+- Group modules by package in the sidebar (#34)
44+
45+Bugfixes:
46+- Fix CLI autocompleter (now works correctly with capital letters).
47+
48+## [0.0.8 - 2020-01-18]
49+
50+Skipped due to failed deployment.
51+
52+## [0.0.7 - 2020-01-18]
53+
54+Changes:
55+- Consider something a builtin when there's no `sourceSpan` (#32)
56+
857## [0.0.6 - 2019-11-29]
958
1059New features:
README.md+4−4
@@ -1,8 +1,8 @@
11# purescript-docs-search
22
3−[![Build status](https://travis-ci.org/spacchetti/purescript-docs-search.svg?branch=master)](https://travis-ci.org/spacchetti/purescript-docs-search)
3+[![Build status](https://github.com/purescript/purescript-docs-search/actions/workflows/build.yml/badge.svg)](https://github.com/purescript/purescript-docs-search/actions/workflows/build.yml)
44
5−An app that adds search capabilities to generated documentation for purescript code.
5+An app that adds search capabilities to generated documentation for PureScript code.
66
77It supports nearly-all functionality of [Pursuit](https://github.com/purescript/pursuit), including querying by type.
88
@@ -10,7 +10,7 @@ It supports nearly-all functionality of [Pursuit](https://github.com/purescript/
1010
1111When using [spago](https://github.com/spacchetti/spago), you don't need to install this app manually: run `spago docs` or `spago search`.
1212
13−Otherwise, use [npx](https://github.com/npm/npx): `npx purescript-docs-search`.
13+Otherwise, use NPM (`npm install purescript-docs-search`) or [npx](https://github.com/npm/npx): `npx purescript-docs-search`.
1414
1515## Usage
1616
@@ -45,4 +45,4 @@ npm install
4545npm run build # or build-dev to skip JS compression stage
4646```
4747
48−Use `spago docs --no-search && ./dist/purescript-docs-search build-index` to generate the docs and patch them using the local version of the app.
48+Use `spago docs --no-search && ./dist/purescript-docs-search.cjs build-index` to generate the docs and patch them using the local version of the app.
ci-npmrc.txtnew file+4
@@ -0,0 +1,4 @@
1+//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
2+registry=https://registry.npmjs.org/
3+always-auth=true
4+
package-lock.jsonnew file+2285
@@ -0,0 +1,2285 @@
1+{
2+ "name": "purescript-docs-search",
3+ "version": "0.0.11",
4+ "lockfileVersion": 2,
5+ "requires": true,
6+ "packages": {
7+ "": {
8+ "name": "purescript-docs-search",
9+ "version": "0.0.11",
10+ "license": "BSD-3-Clause",
11+ "dependencies": {
12+ "punycode": "^2.1.1"
13+ },
14+ "bin": {
15+ "purescript-docs-search": "dist/purescript-docs-search.js"
16+ },
17+ "devDependencies": {
18+ "esbuild": "^0.11.10",
19+ "glob": "^7.1.6",
20+ "markdown-it": "^12.0.4",
21+ "puppeteer": "^8.0.0",
22+ "spago": "^0.20.9"
23+ }
24+ },
25+ "node_modules/@gar/promisify": {
26+ "version": "1.1.3",
27+ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
28+ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
29+ "dev": true
30+ },
31+ "node_modules/@npmcli/fs": {
32+ "version": "1.1.1",
33+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
34+ "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
35+ "dev": true,
36+ "dependencies": {
37+ "@gar/promisify": "^1.0.1",
38+ "semver": "^7.3.5"
39+ }
40+ },
41+ "node_modules/@npmcli/move-file": {
42+ "version": "1.1.2",
43+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
44+ "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
45+ "dev": true,
46+ "dependencies": {
47+ "mkdirp": "^1.0.4",
48+ "rimraf": "^3.0.2"
49+ },
50+ "engines": {
51+ "node": ">=10"
52+ }
53+ },
54+ "node_modules/@tootallnate/once": {
55+ "version": "1.1.2",
56+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
57+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
58+ "dev": true,
59+ "engines": {
60+ "node": ">= 6"
61+ }
62+ },
63+ "node_modules/@types/node": {
64+ "version": "14.14.39",
65+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.39.tgz",
66+ "integrity": "sha512-Qipn7rfTxGEDqZiezH+wxqWYR8vcXq5LRpZrETD19Gs4o8LbklbmqotSUsMU+s5G3PJwMRDfNEYoxrcBwIxOuw==",
67+ "dev": true,
68+ "optional": true
69+ },
70+ "node_modules/@types/yauzl": {
71+ "version": "2.9.1",
72+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
73+ "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==",
74+ "dev": true,
75+ "optional": true,
76+ "dependencies": {
77+ "@types/node": "*"
78+ }
79+ },
80+ "node_modules/agent-base": {
81+ "version": "6.0.2",
82+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
83+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
84+ "dev": true,
85+ "dependencies": {
86+ "debug": "4"
87+ },
88+ "engines": {
89+ "node": ">= 6.0.0"
90+ }
91+ },
92+ "node_modules/agentkeepalive": {
93+ "version": "4.2.1",
94+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz",
95+ "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==",
96+ "dev": true,
97+ "dependencies": {
98+ "debug": "^4.1.0",
99+ "depd": "^1.1.2",
100+ "humanize-ms": "^1.2.1"
101+ },
102+ "engines": {
103+ "node": ">= 8.0.0"
104+ }
105+ },
106+ "node_modules/aggregate-error": {
107+ "version": "3.1.0",
108+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
109+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
110+ "dev": true,
111+ "dependencies": {
112+ "clean-stack": "^2.0.0",
113+ "indent-string": "^4.0.0"
114+ },
115+ "engines": {
116+ "node": ">=8"
117+ }
118+ },
119+ "node_modules/argparse": {
120+ "version": "2.0.1",
121+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
122+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
123+ "dev": true
124+ },
125+ "node_modules/balanced-match": {
126+ "version": "1.0.0",
127+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
128+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
129+ "dev": true
130+ },
131+ "node_modules/base64-js": {
132+ "version": "1.5.1",
133+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
134+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
135+ "dev": true,
136+ "funding": [
137+ {
138+ "type": "github",
139+ "url": "https://github.com/sponsors/feross"
140+ },
141+ {
142+ "type": "patreon",
143+ "url": "https://www.patreon.com/feross"
144+ },
145+ {
146+ "type": "consulting",
147+ "url": "https://feross.org/support"
148+ }
149+ ]
150+ },
151+ "node_modules/bl": {
152+ "version": "4.1.0",
153+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
154+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
155+ "dev": true,
156+ "dependencies": {
157+ "buffer": "^5.5.0",
158+ "inherits": "^2.0.4",
159+ "readable-stream": "^3.4.0"
160+ }
161+ },
162+ "node_modules/bl/node_modules/buffer": {
163+ "version": "5.7.1",
164+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
165+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
166+ "dev": true,
167+ "funding": [
168+ {
169+ "type": "github",
170+ "url": "https://github.com/sponsors/feross"
171+ },
172+ {
173+ "type": "patreon",
174+ "url": "https://www.patreon.com/feross"
175+ },
176+ {
177+ "type": "consulting",
178+ "url": "https://feross.org/support"
179+ }
180+ ],
181+ "dependencies": {
182+ "base64-js": "^1.3.1",
183+ "ieee754": "^1.1.13"
184+ }
185+ },
186+ "node_modules/bl/node_modules/readable-stream": {
187+ "version": "3.6.0",
188+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
189+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
190+ "dev": true,
191+ "dependencies": {
192+ "inherits": "^2.0.3",
193+ "string_decoder": "^1.1.1",
194+ "util-deprecate": "^1.0.1"
195+ },
196+ "engines": {
197+ "node": ">= 6"
198+ }
199+ },
200+ "node_modules/brace-expansion": {
201+ "version": "1.1.11",
202+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
203+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
204+ "dev": true,
205+ "dependencies": {
206+ "balanced-match": "^1.0.0",
207+ "concat-map": "0.0.1"
208+ }
209+ },
210+ "node_modules/buffer-crc32": {
211+ "version": "0.2.13",
212+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
213+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
214+ "dev": true,
215+ "engines": {
216+ "node": "*"
217+ }
218+ },
219+ "node_modules/cacache": {
220+ "version": "15.3.0",
221+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
222+ "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
223+ "dev": true,
224+ "dependencies": {
225+ "@npmcli/fs": "^1.0.0",
226+ "@npmcli/move-file": "^1.0.1",
227+ "chownr": "^2.0.0",
228+ "fs-minipass": "^2.0.0",
229+ "glob": "^7.1.4",
230+ "infer-owner": "^1.0.4",
231+ "lru-cache": "^6.0.0",
232+ "minipass": "^3.1.1",
233+ "minipass-collect": "^1.0.2",
234+ "minipass-flush": "^1.0.5",
235+ "minipass-pipeline": "^1.2.2",
236+ "mkdirp": "^1.0.3",
237+ "p-map": "^4.0.0",
238+ "promise-inflight": "^1.0.1",
239+ "rimraf": "^3.0.2",
240+ "ssri": "^8.0.1",
241+ "tar": "^6.0.2",
242+ "unique-filename": "^1.1.1"
243+ },
244+ "engines": {
245+ "node": ">= 10"
246+ }
247+ },
248+ "node_modules/cacache/node_modules/chownr": {
249+ "version": "2.0.0",
250+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
251+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
252+ "dev": true,
253+ "engines": {
254+ "node": ">=10"
255+ }
256+ },
257+ "node_modules/chownr": {
258+ "version": "1.1.4",
259+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
260+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
261+ "dev": true
262+ },
263+ "node_modules/clean-stack": {
264+ "version": "2.2.0",
265+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
266+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
267+ "dev": true,
268+ "engines": {
269+ "node": ">=6"
270+ }
271+ },
272+ "node_modules/concat-map": {
273+ "version": "0.0.1",
274+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
275+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
276+ "dev": true
277+ },
278+ "node_modules/debug": {
279+ "version": "4.3.4",
280+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
281+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
282+ "dev": true,
283+ "dependencies": {
284+ "ms": "2.1.2"
285+ },
286+ "engines": {
287+ "node": ">=6.0"
288+ },
289+ "peerDependenciesMeta": {
290+ "supports-color": {
291+ "optional": true
292+ }
293+ }
294+ },
295+ "node_modules/depd": {
296+ "version": "1.1.2",
297+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
298+ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
299+ "dev": true,
300+ "engines": {
301+ "node": ">= 0.6"
302+ }
303+ },
304+ "node_modules/devtools-protocol": {
305+ "version": "0.0.854822",
306+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.854822.tgz",
307+ "integrity": "sha512-xd4D8kHQtB0KtWW0c9xBZD5LVtm9chkMOfs/3Yn01RhT/sFIsVtzTtypfKoFfWBaL+7xCYLxjOLkhwPXaX/Kcg==",
308+ "dev": true
309+ },
310+ "node_modules/encoding": {
311+ "version": "0.1.13",
312+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
313+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
314+ "dev": true,
315+ "optional": true,
316+ "dependencies": {
317+ "iconv-lite": "^0.6.2"
318+ }
319+ },
320+ "node_modules/end-of-stream": {
321+ "version": "1.4.4",
322+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
323+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
324+ "dev": true,
325+ "dependencies": {
326+ "once": "^1.4.0"
327+ }
328+ },
329+ "node_modules/entities": {
330+ "version": "2.1.0",
331+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
332+ "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
333+ "dev": true,
334+ "funding": {
335+ "url": "https://github.com/fb55/entities?sponsor=1"
336+ }
337+ },
338+ "node_modules/err-code": {
339+ "version": "2.0.3",
340+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
341+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
342+ "dev": true
343+ },
344+ "node_modules/esbuild": {
345+ "version": "0.11.11",
346+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.11.11.tgz",
347+ "integrity": "sha512-iq5YdV63vY/nUAFIvY92BXVkYjMbOchnofLKoLKMPZIa4uuIJAJG9WRA+ZRjQBZbrsORUwvZcANeG2d3p46PJQ==",
348+ "dev": true,
349+ "hasInstallScript": true,
350+ "bin": {
351+ "esbuild": "bin/esbuild"
352+ }
353+ },
354+ "node_modules/extract-zip": {
355+ "version": "2.0.1",
356+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
357+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
358+ "dev": true,
359+ "dependencies": {
360+ "debug": "^4.1.1",
361+ "get-stream": "^5.1.0",
362+ "yauzl": "^2.10.0"
363+ },
364+ "bin": {
365+ "extract-zip": "cli.js"
366+ },
367+ "engines": {
368+ "node": ">= 10.17.0"
369+ },
370+ "optionalDependencies": {
371+ "@types/yauzl": "^2.9.1"
372+ }
373+ },
374+ "node_modules/fd-slicer": {
375+ "version": "1.1.0",
376+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
377+ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
378+ "dev": true,
379+ "dependencies": {
380+ "pend": "~1.2.0"
381+ }
382+ },
383+ "node_modules/fs-constants": {
384+ "version": "1.0.0",
385+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
386+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
387+ "dev": true
388+ },
389+ "node_modules/fs-minipass": {
390+ "version": "2.1.0",
391+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
392+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
393+ "dev": true,
394+ "dependencies": {
395+ "minipass": "^3.0.0"
396+ },
397+ "engines": {
398+ "node": ">= 8"
399+ }
400+ },
401+ "node_modules/fs.realpath": {
402+ "version": "1.0.0",
403+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
404+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
405+ "dev": true
406+ },
407+ "node_modules/get-stream": {
408+ "version": "5.2.0",
409+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
410+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
411+ "dev": true,
412+ "dependencies": {
413+ "pump": "^3.0.0"
414+ },
415+ "engines": {
416+ "node": ">=8"
417+ },
418+ "funding": {
419+ "url": "https://github.com/sponsors/sindresorhus"
420+ }
421+ },
422+ "node_modules/glob": {
423+ "version": "7.1.6",
424+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
425+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
426+ "dev": true,
427+ "dependencies": {
428+ "fs.realpath": "^1.0.0",
429+ "inflight": "^1.0.4",
430+ "inherits": "2",
431+ "minimatch": "^3.0.4",
432+ "once": "^1.3.0",
433+ "path-is-absolute": "^1.0.0"
434+ },
435+ "engines": {
436+ "node": "*"
437+ },
438+ "funding": {
439+ "url": "https://github.com/sponsors/isaacs"
440+ }
441+ },
442+ "node_modules/http-cache-semantics": {
443+ "version": "4.1.0",
444+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
445+ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
446+ "dev": true
447+ },
448+ "node_modules/http-proxy-agent": {
449+ "version": "4.0.1",
450+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
451+ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
452+ "dev": true,
453+ "dependencies": {
454+ "@tootallnate/once": "1",
455+ "agent-base": "6",
456+ "debug": "4"
457+ },
458+ "engines": {
459+ "node": ">= 6"
460+ }
461+ },
462+ "node_modules/https-proxy-agent": {
463+ "version": "5.0.0",
464+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
465+ "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
466+ "dev": true,
467+ "dependencies": {
468+ "agent-base": "6",
469+ "debug": "4"
470+ },
471+ "engines": {
472+ "node": ">= 6"
473+ }
474+ },
475+ "node_modules/humanize-ms": {
476+ "version": "1.2.1",
477+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
478+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
479+ "dev": true,
480+ "dependencies": {
481+ "ms": "^2.0.0"
482+ }
483+ },
484+ "node_modules/iconv-lite": {
485+ "version": "0.6.3",
486+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
487+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
488+ "dev": true,
489+ "optional": true,
490+ "dependencies": {
491+ "safer-buffer": ">= 2.1.2 < 3.0.0"
492+ },
493+ "engines": {
494+ "node": ">=0.10.0"
495+ }
496+ },
497+ "node_modules/ieee754": {
498+ "version": "1.2.1",
499+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
500+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
501+ "dev": true,
502+ "funding": [
503+ {
504+ "type": "github",
505+ "url": "https://github.com/sponsors/feross"
506+ },
507+ {
508+ "type": "patreon",
509+ "url": "https://www.patreon.com/feross"
510+ },
511+ {
512+ "type": "consulting",
513+ "url": "https://feross.org/support"
514+ }
515+ ]
516+ },
517+ "node_modules/imurmurhash": {
518+ "version": "0.1.4",
519+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
520+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
521+ "dev": true,
522+ "engines": {
523+ "node": ">=0.8.19"
524+ }
525+ },
526+ "node_modules/indent-string": {
527+ "version": "4.0.0",
528+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
529+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
530+ "dev": true,
531+ "engines": {
532+ "node": ">=8"
533+ }
534+ },
535+ "node_modules/infer-owner": {
536+ "version": "1.0.4",
537+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
538+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
539+ "dev": true
540+ },
541+ "node_modules/inflight": {
542+ "version": "1.0.6",
543+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
544+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
545+ "dev": true,
546+ "dependencies": {
547+ "once": "^1.3.0",
548+ "wrappy": "1"
549+ }
550+ },
551+ "node_modules/inherits": {
552+ "version": "2.0.4",
553+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
554+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
555+ "dev": true
556+ },
557+ "node_modules/ip": {
558+ "version": "2.0.0",
559+ "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
560+ "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
561+ "dev": true
562+ },
563+ "node_modules/is-lambda": {
564+ "version": "1.0.1",
565+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
566+ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
567+ "dev": true
568+ },
569+ "node_modules/linkify-it": {
570+ "version": "3.0.3",
571+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
572+ "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
573+ "dev": true,
574+ "dependencies": {
575+ "uc.micro": "^1.0.1"
576+ }
577+ },
578+ "node_modules/lru-cache": {
579+ "version": "6.0.0",
580+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
581+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
582+ "dev": true,
583+ "dependencies": {
584+ "yallist": "^4.0.0"
585+ },
586+ "engines": {
587+ "node": ">=10"
588+ }
589+ },
590+ "node_modules/make-fetch-happen": {
591+ "version": "9.1.0",
592+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
593+ "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
594+ "dev": true,
595+ "dependencies": {
596+ "agentkeepalive": "^4.1.3",
597+ "cacache": "^15.2.0",
598+ "http-cache-semantics": "^4.1.0",
599+ "http-proxy-agent": "^4.0.1",
600+ "https-proxy-agent": "^5.0.0",
601+ "is-lambda": "^1.0.1",
602+ "lru-cache": "^6.0.0",
603+ "minipass": "^3.1.3",
604+ "minipass-collect": "^1.0.2",
605+ "minipass-fetch": "^1.3.2",
606+ "minipass-flush": "^1.0.5",
607+ "minipass-pipeline": "^1.2.4",
608+ "negotiator": "^0.6.2",
609+ "promise-retry": "^2.0.1",
610+ "socks-proxy-agent": "^6.0.0",
611+ "ssri": "^8.0.0"
612+ },
613+ "engines": {
614+ "node": ">= 10"
615+ }
616+ },
617+ "node_modules/markdown-it": {
618+ "version": "12.3.2",
619+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
620+ "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
621+ "dev": true,
622+ "dependencies": {
623+ "argparse": "^2.0.1",
624+ "entities": "~2.1.0",
625+ "linkify-it": "^3.0.1",
626+ "mdurl": "^1.0.1",
627+ "uc.micro": "^1.0.5"
628+ },
629+ "bin": {
630+ "markdown-it": "bin/markdown-it.js"
631+ }
632+ },
633+ "node_modules/mdurl": {
634+ "version": "1.0.1",
635+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
636+ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
637+ "dev": true
638+ },
639+ "node_modules/minimatch": {
640+ "version": "3.0.4",
641+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
642+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
643+ "dev": true,
644+ "dependencies": {
645+ "brace-expansion": "^1.1.7"
646+ },
647+ "engines": {
648+ "node": "*"
649+ }
650+ },
651+ "node_modules/minipass": {
652+ "version": "3.3.4",
653+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz",
654+ "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==",
655+ "dev": true,
656+ "dependencies": {
657+ "yallist": "^4.0.0"
658+ },
659+ "engines": {
660+ "node": ">=8"
661+ }
662+ },
663+ "node_modules/minipass-collect": {
664+ "version": "1.0.2",
665+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
666+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
667+ "dev": true,
668+ "dependencies": {
669+ "minipass": "^3.0.0"
670+ },
671+ "engines": {
672+ "node": ">= 8"
673+ }
674+ },
675+ "node_modules/minipass-fetch": {
676+ "version": "1.4.1",
677+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
678+ "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
679+ "dev": true,
680+ "dependencies": {
681+ "minipass": "^3.1.0",
682+ "minipass-sized": "^1.0.3",
683+ "minizlib": "^2.0.0"
684+ },
685+ "engines": {
686+ "node": ">=8"
687+ },
688+ "optionalDependencies": {
689+ "encoding": "^0.1.12"
690+ }
691+ },
692+ "node_modules/minipass-flush": {
693+ "version": "1.0.5",
694+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
695+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
696+ "dev": true,
697+ "dependencies": {
698+ "minipass": "^3.0.0"
699+ },
700+ "engines": {
701+ "node": ">= 8"
702+ }
703+ },
704+ "node_modules/minipass-pipeline": {
705+ "version": "1.2.4",
706+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
707+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
708+ "dev": true,
709+ "dependencies": {
710+ "minipass": "^3.0.0"
711+ },
712+ "engines": {
713+ "node": ">=8"
714+ }
715+ },
716+ "node_modules/minipass-sized": {
717+ "version": "1.0.3",
718+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
719+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
720+ "dev": true,
721+ "dependencies": {
722+ "minipass": "^3.0.0"
723+ },
724+ "engines": {
725+ "node": ">=8"
726+ }
727+ },
728+ "node_modules/minizlib": {
729+ "version": "2.1.2",
730+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
731+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
732+ "dev": true,
733+ "dependencies": {
734+ "minipass": "^3.0.0",
735+ "yallist": "^4.0.0"
736+ },
737+ "engines": {
738+ "node": ">= 8"
739+ }
740+ },
741+ "node_modules/mkdirp": {
742+ "version": "1.0.4",
743+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
744+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
745+ "dev": true,
746+ "bin": {
747+ "mkdirp": "bin/cmd.js"
748+ },
749+ "engines": {
750+ "node": ">=10"
751+ }
752+ },
753+ "node_modules/mkdirp-classic": {
754+ "version": "0.5.3",
755+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
756+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
757+ "dev": true
758+ },
759+ "node_modules/ms": {
760+ "version": "2.1.2",
761+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
762+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
763+ "dev": true
764+ },
765+ "node_modules/negotiator": {
766+ "version": "0.6.3",
767+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
768+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
769+ "dev": true,
770+ "engines": {
771+ "node": ">= 0.6"
772+ }
773+ },
774+ "node_modules/node-fetch": {
775+ "version": "2.6.1",
776+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
777+ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
778+ "dev": true,
779+ "engines": {
780+ "node": "4.x || >=6.0.0"
781+ }
782+ },
783+ "node_modules/once": {
784+ "version": "1.4.0",
785+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
786+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
787+ "dev": true,
788+ "dependencies": {
789+ "wrappy": "1"
790+ }
791+ },
792+ "node_modules/p-limit": {
793+ "version": "2.3.0",
794+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
795+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
796+ "dev": true,
797+ "dependencies": {
798+ "p-try": "^2.0.0"
799+ },
800+ "engines": {
801+ "node": ">=6"
802+ },
803+ "funding": {
804+ "url": "https://github.com/sponsors/sindresorhus"
805+ }
806+ },
807+ "node_modules/p-map": {
808+ "version": "4.0.0",
809+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
810+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
811+ "dev": true,
812+ "dependencies": {
813+ "aggregate-error": "^3.0.0"
814+ },
815+ "engines": {
816+ "node": ">=10"
817+ },
818+ "funding": {
819+ "url": "https://github.com/sponsors/sindresorhus"
820+ }
821+ },
822+ "node_modules/p-try": {
823+ "version": "2.2.0",
824+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
825+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
826+ "dev": true,
827+ "engines": {
828+ "node": ">=6"
829+ }
830+ },
831+ "node_modules/path-is-absolute": {
832+ "version": "1.0.1",
833+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
834+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
835+ "dev": true,
836+ "engines": {
837+ "node": ">=0.10.0"
838+ }
839+ },
840+ "node_modules/pend": {
841+ "version": "1.2.0",
842+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
843+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
844+ "dev": true
845+ },
846+ "node_modules/pkg-dir": {
847+ "version": "4.2.0",
848+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
849+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
850+ "dev": true,
851+ "dependencies": {
852+ "find-up": "^4.0.0"
853+ },
854+ "engines": {
855+ "node": ">=8"
856+ }
857+ },
858+ "node_modules/pkg-dir/node_modules/find-up": {
859+ "version": "4.1.0",
860+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
861+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
862+ "dev": true,
863+ "dependencies": {
864+ "locate-path": "^5.0.0",
865+ "path-exists": "^4.0.0"
866+ },
867+ "engines": {
868+ "node": ">=8"
869+ }
870+ },
871+ "node_modules/pkg-dir/node_modules/locate-path": {
872+ "version": "5.0.0",
873+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
874+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
875+ "dev": true,
876+ "dependencies": {
877+ "p-locate": "^4.1.0"
878+ },
879+ "engines": {
880+ "node": ">=8"
881+ }
882+ },
883+ "node_modules/pkg-dir/node_modules/p-locate": {
884+ "version": "4.1.0",
885+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
886+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
887+ "dev": true,
888+ "dependencies": {
889+ "p-limit": "^2.2.0"
890+ },
891+ "engines": {
892+ "node": ">=8"
893+ }
894+ },
895+ "node_modules/pkg-dir/node_modules/path-exists": {
896+ "version": "4.0.0",
897+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
898+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
899+ "dev": true,
900+ "engines": {
901+ "node": ">=8"
902+ }
903+ },
904+ "node_modules/progress": {
905+ "version": "2.0.3",
906+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
907+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
908+ "dev": true,
909+ "engines": {
910+ "node": ">=0.4.0"
911+ }
912+ },
913+ "node_modules/promise-inflight": {
914+ "version": "1.0.1",
915+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
916+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
917+ "dev": true
918+ },
919+ "node_modules/promise-retry": {
920+ "version": "2.0.1",
921+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
922+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
923+ "dev": true,
924+ "dependencies": {
925+ "err-code": "^2.0.2",
926+ "retry": "^0.12.0"
927+ },
928+ "engines": {
929+ "node": ">=10"
930+ }
931+ },
932+ "node_modules/proxy-from-env": {
933+ "version": "1.1.0",
934+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
935+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
936+ "dev": true
937+ },
938+ "node_modules/pump": {
939+ "version": "3.0.0",
940+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
941+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
942+ "dev": true,
943+ "dependencies": {
944+ "end-of-stream": "^1.1.0",
945+ "once": "^1.3.1"
946+ }
947+ },
948+ "node_modules/punycode": {
949+ "version": "2.1.1",
950+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
951+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
952+ "engines": {
953+ "node": ">=6"
954+ }
955+ },
956+ "node_modules/puppeteer": {
957+ "version": "8.0.0",
958+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-8.0.0.tgz",
959+ "integrity": "sha512-D0RzSWlepeWkxPPdK3xhTcefj8rjah1791GE82Pdjsri49sy11ci/JQsAO8K2NRukqvwEtcI+ImP5F4ZiMvtIQ==",
960+ "deprecated": "Version no longer supported. Upgrade to @latest",
961+ "dev": true,
962+ "hasInstallScript": true,
963+ "dependencies": {
964+ "debug": "^4.1.0",
965+ "devtools-protocol": "0.0.854822",
966+ "extract-zip": "^2.0.0",
967+ "https-proxy-agent": "^5.0.0",
968+ "node-fetch": "^2.6.1",
969+ "pkg-dir": "^4.2.0",
970+ "progress": "^2.0.1",
971+ "proxy-from-env": "^1.1.0",
972+ "rimraf": "^3.0.2",
973+ "tar-fs": "^2.0.0",
974+ "unbzip2-stream": "^1.3.3",
975+ "ws": "^7.2.3"
976+ },
977+ "engines": {
978+ "node": ">=10.18.1"
979+ }
980+ },
981+ "node_modules/puppeteer/node_modules/ws": {
982+ "version": "7.4.4",
983+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz",
984+ "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==",
985+ "dev": true,
986+ "engines": {
987+ "node": ">=8.3.0"
988+ },
989+ "peerDependencies": {
990+ "bufferutil": "^4.0.1",
991+ "utf-8-validate": "^5.0.2"
992+ },
993+ "peerDependenciesMeta": {
994+ "bufferutil": {
995+ "optional": true
996+ },
997+ "utf-8-validate": {
998+ "optional": true
999+ }
1000+ }
1001+ },
1002+ "node_modules/retry": {
1003+ "version": "0.12.0",
1004+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
1005+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
1006+ "dev": true,
1007+ "engines": {
1008+ "node": ">= 4"
1009+ }
1010+ },
1011+ "node_modules/rimraf": {
1012+ "version": "3.0.2",
1013+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
1014+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
1015+ "dev": true,
1016+ "dependencies": {
1017+ "glob": "^7.1.3"
1018+ },
1019+ "bin": {
1020+ "rimraf": "bin.js"
1021+ },
1022+ "funding": {
1023+ "url": "https://github.com/sponsors/isaacs"
1024+ }
1025+ },
1026+ "node_modules/safe-buffer": {
1027+ "version": "5.2.1",
1028+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1029+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1030+ "dev": true,
1031+ "funding": [
1032+ {
1033+ "type": "github",
1034+ "url": "https://github.com/sponsors/feross"
1035+ },
1036+ {
1037+ "type": "patreon",
1038+ "url": "https://www.patreon.com/feross"
1039+ },
1040+ {
1041+ "type": "consulting",
1042+ "url": "https://feross.org/support"
1043+ }
1044+ ]
1045+ },
1046+ "node_modules/safer-buffer": {
1047+ "version": "2.1.2",
1048+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1049+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
1050+ "dev": true,
1051+ "optional": true
1052+ },
1053+ "node_modules/semver": {
1054+ "version": "7.3.7",
1055+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
1056+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
1057+ "dev": true,
1058+ "dependencies": {
1059+ "lru-cache": "^6.0.0"
1060+ },
1061+ "bin": {
1062+ "semver": "bin/semver.js"
1063+ },
1064+ "engines": {
1065+ "node": ">=10"
1066+ }
1067+ },
1068+ "node_modules/smart-buffer": {
1069+ "version": "4.2.0",
1070+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
1071+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
1072+ "dev": true,
1073+ "engines": {
1074+ "node": ">= 6.0.0",
1075+ "npm": ">= 3.0.0"
1076+ }
1077+ },
1078+ "node_modules/socks": {
1079+ "version": "2.7.0",
1080+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz",
1081+ "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==",
1082+ "dev": true,
1083+ "dependencies": {
1084+ "ip": "^2.0.0",
1085+ "smart-buffer": "^4.2.0"
1086+ },
1087+ "engines": {
1088+ "node": ">= 10.13.0",
1089+ "npm": ">= 3.0.0"
1090+ }
1091+ },
1092+ "node_modules/socks-proxy-agent": {
1093+ "version": "6.2.1",
1094+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz",
1095+ "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==",
1096+ "dev": true,
1097+ "dependencies": {
1098+ "agent-base": "^6.0.2",
1099+ "debug": "^4.3.3",
1100+ "socks": "^2.6.2"
1101+ },
1102+ "engines": {
1103+ "node": ">= 10"
1104+ }
1105+ },
1106+ "node_modules/spago": {
1107+ "version": "0.20.9",
1108+ "resolved": "https://registry.npmjs.org/spago/-/spago-0.20.9.tgz",
1109+ "integrity": "sha512-r5TUxnYn9HawlQyMswlhIk24BGFSN2KGbqgZFZrn47GjTpMscU14xkt9CqTWgoSQYsoZieG+3dUtOxUQ7GYD7w==",
1110+ "dev": true,
1111+ "hasInstallScript": true,
1112+ "dependencies": {
1113+ "make-fetch-happen": "^9.1.0",
1114+ "tar": "^6.1.11"
1115+ },
1116+ "bin": {
1117+ "spago": "spago"
1118+ }
1119+ },
1120+ "node_modules/ssri": {
1121+ "version": "8.0.1",
1122+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
1123+ "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
1124+ "dev": true,
1125+ "dependencies": {
1126+ "minipass": "^3.1.1"
1127+ },
1128+ "engines": {
1129+ "node": ">= 8"
1130+ }
1131+ },
1132+ "node_modules/string_decoder": {
1133+ "version": "1.3.0",
1134+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
1135+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
1136+ "dev": true,
1137+ "dependencies": {
1138+ "safe-buffer": "~5.2.0"
1139+ }
1140+ },
1141+ "node_modules/tar": {
1142+ "version": "6.1.11",
1143+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
1144+ "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
1145+ "dev": true,
1146+ "dependencies": {
1147+ "chownr": "^2.0.0",
1148+ "fs-minipass": "^2.0.0",
1149+ "minipass": "^3.0.0",
1150+ "minizlib": "^2.1.1",
1151+ "mkdirp": "^1.0.3",
1152+ "yallist": "^4.0.0"
1153+ },
1154+ "engines": {
1155+ "node": ">= 10"
1156+ }
1157+ },
1158+ "node_modules/tar-fs": {
1159+ "version": "2.1.1",
1160+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
1161+ "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
1162+ "dev": true,
1163+ "dependencies": {
1164+ "chownr": "^1.1.1",
1165+ "mkdirp-classic": "^0.5.2",
1166+ "pump": "^3.0.0",
1167+ "tar-stream": "^2.1.4"
1168+ }
1169+ },
1170+ "node_modules/tar-stream": {
1171+ "version": "2.2.0",
1172+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
1173+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
1174+ "dev": true,
1175+ "dependencies": {
1176+ "bl": "^4.0.3",
1177+ "end-of-stream": "^1.4.1",
1178+ "fs-constants": "^1.0.0",
1179+ "inherits": "^2.0.3",
1180+ "readable-stream": "^3.1.1"
1181+ },
1182+ "engines": {
1183+ "node": ">=6"
1184+ }
1185+ },
1186+ "node_modules/tar-stream/node_modules/readable-stream": {
1187+ "version": "3.6.0",
1188+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
1189+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
1190+ "dev": true,
1191+ "dependencies": {
1192+ "inherits": "^2.0.3",
1193+ "string_decoder": "^1.1.1",
1194+ "util-deprecate": "^1.0.1"
1195+ },
1196+ "engines": {
1197+ "node": ">= 6"
1198+ }
1199+ },
1200+ "node_modules/tar/node_modules/chownr": {
1201+ "version": "2.0.0",
1202+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
1203+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
1204+ "dev": true,
1205+ "engines": {
1206+ "node": ">=10"
1207+ }
1208+ },
1209+ "node_modules/through": {
1210+ "version": "2.3.8",
1211+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
1212+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
1213+ "dev": true
1214+ },
1215+ "node_modules/uc.micro": {
1216+ "version": "1.0.6",
1217+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
1218+ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
1219+ "dev": true
1220+ },
1221+ "node_modules/unbzip2-stream": {
1222+ "version": "1.4.3",
1223+ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
1224+ "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
1225+ "dev": true,
1226+ "dependencies": {
1227+ "buffer": "^5.2.1",
1228+ "through": "^2.3.8"
1229+ }
1230+ },
1231+ "node_modules/unbzip2-stream/node_modules/buffer": {
1232+ "version": "5.7.1",
1233+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
1234+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
1235+ "dev": true,
1236+ "funding": [
1237+ {
1238+ "type": "github",
1239+ "url": "https://github.com/sponsors/feross"
1240+ },
1241+ {
1242+ "type": "patreon",
1243+ "url": "https://www.patreon.com/feross"
1244+ },
1245+ {
1246+ "type": "consulting",
1247+ "url": "https://feross.org/support"
1248+ }
1249+ ],
1250+ "dependencies": {
1251+ "base64-js": "^1.3.1",
1252+ "ieee754": "^1.1.13"
1253+ }
1254+ },
1255+ "node_modules/unique-filename": {
1256+ "version": "1.1.1",
1257+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
1258+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
1259+ "dev": true,
1260+ "dependencies": {
1261+ "unique-slug": "^2.0.0"
1262+ }
1263+ },
1264+ "node_modules/unique-slug": {
1265+ "version": "2.0.2",
1266+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
1267+ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
1268+ "dev": true,
1269+ "dependencies": {
1270+ "imurmurhash": "^0.1.4"
1271+ }
1272+ },
1273+ "node_modules/util-deprecate": {
1274+ "version": "1.0.2",
1275+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1276+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
1277+ "dev": true
1278+ },
1279+ "node_modules/wrappy": {
1280+ "version": "1.0.2",
1281+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1282+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
1283+ "dev": true
1284+ },
1285+ "node_modules/yallist": {
1286+ "version": "4.0.0",
1287+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
1288+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
1289+ "dev": true
1290+ },
1291+ "node_modules/yauzl": {
1292+ "version": "2.10.0",
1293+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
1294+ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
1295+ "dev": true,
1296+ "dependencies": {
1297+ "buffer-crc32": "~0.2.3",
1298+ "fd-slicer": "~1.1.0"
1299+ }
1300+ }
1301+ },
1302+ "dependencies": {
1303+ "@gar/promisify": {
1304+ "version": "1.1.3",
1305+ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
1306+ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
1307+ "dev": true
1308+ },
1309+ "@npmcli/fs": {
1310+ "version": "1.1.1",
1311+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
1312+ "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
1313+ "dev": true,
1314+ "requires": {
1315+ "@gar/promisify": "^1.0.1",
1316+ "semver": "^7.3.5"
1317+ }
1318+ },
1319+ "@npmcli/move-file": {
1320+ "version": "1.1.2",
1321+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
1322+ "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
1323+ "dev": true,
1324+ "requires": {
1325+ "mkdirp": "^1.0.4",
1326+ "rimraf": "^3.0.2"
1327+ }
1328+ },
1329+ "@tootallnate/once": {
1330+ "version": "1.1.2",
1331+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
1332+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
1333+ "dev": true
1334+ },
1335+ "@types/node": {
1336+ "version": "14.14.39",
1337+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.39.tgz",
1338+ "integrity": "sha512-Qipn7rfTxGEDqZiezH+wxqWYR8vcXq5LRpZrETD19Gs4o8LbklbmqotSUsMU+s5G3PJwMRDfNEYoxrcBwIxOuw==",
1339+ "dev": true,
1340+ "optional": true
1341+ },
1342+ "@types/yauzl": {
1343+ "version": "2.9.1",
1344+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
1345+ "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==",
1346+ "dev": true,
1347+ "optional": true,
1348+ "requires": {
1349+ "@types/node": "*"
1350+ }
1351+ },
1352+ "agent-base": {
1353+ "version": "6.0.2",
1354+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
1355+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
1356+ "dev": true,
1357+ "requires": {
1358+ "debug": "4"
1359+ }
1360+ },
1361+ "agentkeepalive": {
1362+ "version": "4.2.1",
1363+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz",
1364+ "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==",
1365+ "dev": true,
1366+ "requires": {
1367+ "debug": "^4.1.0",
1368+ "depd": "^1.1.2",
1369+ "humanize-ms": "^1.2.1"
1370+ }
1371+ },
1372+ "aggregate-error": {
1373+ "version": "3.1.0",
1374+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
1375+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
1376+ "dev": true,
1377+ "requires": {
1378+ "clean-stack": "^2.0.0",
1379+ "indent-string": "^4.0.0"
1380+ }
1381+ },
1382+ "argparse": {
1383+ "version": "2.0.1",
1384+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
1385+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
1386+ "dev": true
1387+ },
1388+ "balanced-match": {
1389+ "version": "1.0.0",
1390+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
1391+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
1392+ "dev": true
1393+ },
1394+ "base64-js": {
1395+ "version": "1.5.1",
1396+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
1397+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
1398+ "dev": true
1399+ },
1400+ "bl": {
1401+ "version": "4.1.0",
1402+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
1403+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
1404+ "dev": true,
1405+ "requires": {
1406+ "buffer": "^5.5.0",
1407+ "inherits": "^2.0.4",
1408+ "readable-stream": "^3.4.0"
1409+ },
1410+ "dependencies": {
1411+ "buffer": {
1412+ "version": "5.7.1",
1413+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
1414+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
1415+ "dev": true,
1416+ "requires": {
1417+ "base64-js": "^1.3.1",
1418+ "ieee754": "^1.1.13"
1419+ }
1420+ },
1421+ "readable-stream": {
1422+ "version": "3.6.0",
1423+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
1424+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
1425+ "dev": true,
1426+ "requires": {
1427+ "inherits": "^2.0.3",
1428+ "string_decoder": "^1.1.1",
1429+ "util-deprecate": "^1.0.1"
1430+ }
1431+ }
1432+ }
1433+ },
1434+ "brace-expansion": {
1435+ "version": "1.1.11",
1436+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1437+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1438+ "dev": true,
1439+ "requires": {
1440+ "balanced-match": "^1.0.0",
1441+ "concat-map": "0.0.1"
1442+ }
1443+ },
1444+ "buffer-crc32": {
1445+ "version": "0.2.13",
1446+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
1447+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
1448+ "dev": true
1449+ },
1450+ "cacache": {
1451+ "version": "15.3.0",
1452+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
1453+ "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
1454+ "dev": true,
1455+ "requires": {
1456+ "@npmcli/fs": "^1.0.0",
1457+ "@npmcli/move-file": "^1.0.1",
1458+ "chownr": "^2.0.0",
1459+ "fs-minipass": "^2.0.0",
1460+ "glob": "^7.1.4",
1461+ "infer-owner": "^1.0.4",
1462+ "lru-cache": "^6.0.0",
1463+ "minipass": "^3.1.1",
1464+ "minipass-collect": "^1.0.2",
1465+ "minipass-flush": "^1.0.5",
1466+ "minipass-pipeline": "^1.2.2",
1467+ "mkdirp": "^1.0.3",
1468+ "p-map": "^4.0.0",
1469+ "promise-inflight": "^1.0.1",
1470+ "rimraf": "^3.0.2",
1471+ "ssri": "^8.0.1",
1472+ "tar": "^6.0.2",
1473+ "unique-filename": "^1.1.1"
1474+ },
1475+ "dependencies": {
1476+ "chownr": {
1477+ "version": "2.0.0",
1478+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
1479+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
1480+ "dev": true
1481+ }
1482+ }
1483+ },
1484+ "chownr": {
1485+ "version": "1.1.4",
1486+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
1487+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
1488+ "dev": true
1489+ },
1490+ "clean-stack": {
1491+ "version": "2.2.0",
1492+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
1493+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
1494+ "dev": true
1495+ },
1496+ "concat-map": {
1497+ "version": "0.0.1",
1498+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1499+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
1500+ "dev": true
1501+ },
1502+ "debug": {
1503+ "version": "4.3.4",
1504+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
1505+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
1506+ "dev": true,
1507+ "requires": {
1508+ "ms": "2.1.2"
1509+ }
1510+ },
1511+ "depd": {
1512+ "version": "1.1.2",
1513+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
1514+ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
1515+ "dev": true
1516+ },
1517+ "devtools-protocol": {
1518+ "version": "0.0.854822",
1519+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.854822.tgz",
1520+ "integrity": "sha512-xd4D8kHQtB0KtWW0c9xBZD5LVtm9chkMOfs/3Yn01RhT/sFIsVtzTtypfKoFfWBaL+7xCYLxjOLkhwPXaX/Kcg==",
1521+ "dev": true
1522+ },
1523+ "encoding": {
1524+ "version": "0.1.13",
1525+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
1526+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
1527+ "dev": true,
1528+ "optional": true,
1529+ "requires": {
1530+ "iconv-lite": "^0.6.2"
1531+ }
1532+ },
1533+ "end-of-stream": {
1534+ "version": "1.4.4",
1535+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
1536+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
1537+ "dev": true,
1538+ "requires": {
1539+ "once": "^1.4.0"
1540+ }
1541+ },
1542+ "entities": {
1543+ "version": "2.1.0",
1544+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
1545+ "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
1546+ "dev": true
1547+ },
1548+ "err-code": {
1549+ "version": "2.0.3",
1550+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
1551+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
1552+ "dev": true
1553+ },
1554+ "esbuild": {
1555+ "version": "0.11.11",
1556+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.11.11.tgz",
1557+ "integrity": "sha512-iq5YdV63vY/nUAFIvY92BXVkYjMbOchnofLKoLKMPZIa4uuIJAJG9WRA+ZRjQBZbrsORUwvZcANeG2d3p46PJQ==",
1558+ "dev": true
1559+ },
1560+ "extract-zip": {
1561+ "version": "2.0.1",
1562+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
1563+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
1564+ "dev": true,
1565+ "requires": {
1566+ "@types/yauzl": "^2.9.1",
1567+ "debug": "^4.1.1",
1568+ "get-stream": "^5.1.0",
1569+ "yauzl": "^2.10.0"
1570+ }
1571+ },
1572+ "fd-slicer": {
1573+ "version": "1.1.0",
1574+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
1575+ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
1576+ "dev": true,
1577+ "requires": {
1578+ "pend": "~1.2.0"
1579+ }
1580+ },
1581+ "fs-constants": {
1582+ "version": "1.0.0",
1583+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
1584+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
1585+ "dev": true
1586+ },
1587+ "fs-minipass": {
1588+ "version": "2.1.0",
1589+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
1590+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
1591+ "dev": true,
1592+ "requires": {
1593+ "minipass": "^3.0.0"
1594+ }
1595+ },
1596+ "fs.realpath": {
1597+ "version": "1.0.0",
1598+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1599+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
1600+ "dev": true
1601+ },
1602+ "get-stream": {
1603+ "version": "5.2.0",
1604+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
1605+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
1606+ "dev": true,
1607+ "requires": {
1608+ "pump": "^3.0.0"
1609+ }
1610+ },
1611+ "glob": {
1612+ "version": "7.1.6",
1613+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
1614+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
1615+ "dev": true,
1616+ "requires": {
1617+ "fs.realpath": "^1.0.0",
1618+ "inflight": "^1.0.4",
1619+ "inherits": "2",
1620+ "minimatch": "^3.0.4",
1621+ "once": "^1.3.0",
1622+ "path-is-absolute": "^1.0.0"
1623+ }
1624+ },
1625+ "http-cache-semantics": {
1626+ "version": "4.1.0",
1627+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
1628+ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
1629+ "dev": true
1630+ },
1631+ "http-proxy-agent": {
1632+ "version": "4.0.1",
1633+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
1634+ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
1635+ "dev": true,
1636+ "requires": {
1637+ "@tootallnate/once": "1",
1638+ "agent-base": "6",
1639+ "debug": "4"
1640+ }
1641+ },
1642+ "https-proxy-agent": {
1643+ "version": "5.0.0",
1644+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
1645+ "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
1646+ "dev": true,
1647+ "requires": {
1648+ "agent-base": "6",
1649+ "debug": "4"
1650+ }
1651+ },
1652+ "humanize-ms": {
1653+ "version": "1.2.1",
1654+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
1655+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
1656+ "dev": true,
1657+ "requires": {
1658+ "ms": "^2.0.0"
1659+ }
1660+ },
1661+ "iconv-lite": {
1662+ "version": "0.6.3",
1663+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
1664+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
1665+ "dev": true,
1666+ "optional": true,
1667+ "requires": {
1668+ "safer-buffer": ">= 2.1.2 < 3.0.0"
1669+ }
1670+ },
1671+ "ieee754": {
1672+ "version": "1.2.1",
1673+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
1674+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
1675+ "dev": true
1676+ },
1677+ "imurmurhash": {
1678+ "version": "0.1.4",
1679+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
1680+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
1681+ "dev": true
1682+ },
1683+ "indent-string": {
1684+ "version": "4.0.0",
1685+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
1686+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
1687+ "dev": true
1688+ },
1689+ "infer-owner": {
1690+ "version": "1.0.4",
1691+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
1692+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
1693+ "dev": true
1694+ },
1695+ "inflight": {
1696+ "version": "1.0.6",
1697+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
1698+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
1699+ "dev": true,
1700+ "requires": {
1701+ "once": "^1.3.0",
1702+ "wrappy": "1"
1703+ }
1704+ },
1705+ "inherits": {
1706+ "version": "2.0.4",
1707+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1708+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1709+ "dev": true
1710+ },
1711+ "ip": {
1712+ "version": "2.0.0",
1713+ "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
1714+ "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
1715+ "dev": true
1716+ },
1717+ "is-lambda": {
1718+ "version": "1.0.1",
1719+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
1720+ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
1721+ "dev": true
1722+ },
1723+ "linkify-it": {
1724+ "version": "3.0.3",
1725+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
1726+ "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
1727+ "dev": true,
1728+ "requires": {
1729+ "uc.micro": "^1.0.1"
1730+ }
1731+ },
1732+ "lru-cache": {
1733+ "version": "6.0.0",
1734+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
1735+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
1736+ "dev": true,
1737+ "requires": {
1738+ "yallist": "^4.0.0"
1739+ }
1740+ },
1741+ "make-fetch-happen": {
1742+ "version": "9.1.0",
1743+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
1744+ "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
1745+ "dev": true,
1746+ "requires": {
1747+ "agentkeepalive": "^4.1.3",
1748+ "cacache": "^15.2.0",
1749+ "http-cache-semantics": "^4.1.0",
1750+ "http-proxy-agent": "^4.0.1",
1751+ "https-proxy-agent": "^5.0.0",
1752+ "is-lambda": "^1.0.1",
1753+ "lru-cache": "^6.0.0",
1754+ "minipass": "^3.1.3",
1755+ "minipass-collect": "^1.0.2",
1756+ "minipass-fetch": "^1.3.2",
1757+ "minipass-flush": "^1.0.5",
1758+ "minipass-pipeline": "^1.2.4",
1759+ "negotiator": "^0.6.2",
1760+ "promise-retry": "^2.0.1",
1761+ "socks-proxy-agent": "^6.0.0",
1762+ "ssri": "^8.0.0"
1763+ }
1764+ },
1765+ "markdown-it": {
1766+ "version": "12.3.2",
1767+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
1768+ "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
1769+ "dev": true,
1770+ "requires": {
1771+ "argparse": "^2.0.1",
1772+ "entities": "~2.1.0",
1773+ "linkify-it": "^3.0.1",
1774+ "mdurl": "^1.0.1",
1775+ "uc.micro": "^1.0.5"
1776+ }
1777+ },
1778+ "mdurl": {
1779+ "version": "1.0.1",
1780+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
1781+ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
1782+ "dev": true
1783+ },
1784+ "minimatch": {
1785+ "version": "3.0.4",
1786+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
1787+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
1788+ "dev": true,
1789+ "requires": {
1790+ "brace-expansion": "^1.1.7"
1791+ }
1792+ },
1793+ "minipass": {
1794+ "version": "3.3.4",
1795+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz",
1796+ "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==",
1797+ "dev": true,
1798+ "requires": {
1799+ "yallist": "^4.0.0"
1800+ }
1801+ },
1802+ "minipass-collect": {
1803+ "version": "1.0.2",
1804+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
1805+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
1806+ "dev": true,
1807+ "requires": {
1808+ "minipass": "^3.0.0"
1809+ }
1810+ },
1811+ "minipass-fetch": {
1812+ "version": "1.4.1",
1813+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
1814+ "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
1815+ "dev": true,
1816+ "requires": {
1817+ "encoding": "^0.1.12",
1818+ "minipass": "^3.1.0",
1819+ "minipass-sized": "^1.0.3",
1820+ "minizlib": "^2.0.0"
1821+ }
1822+ },
1823+ "minipass-flush": {
1824+ "version": "1.0.5",
1825+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
1826+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
1827+ "dev": true,
1828+ "requires": {
1829+ "minipass": "^3.0.0"
1830+ }
1831+ },
1832+ "minipass-pipeline": {
1833+ "version": "1.2.4",
1834+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
1835+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
1836+ "dev": true,
1837+ "requires": {
1838+ "minipass": "^3.0.0"
1839+ }
1840+ },
1841+ "minipass-sized": {
1842+ "version": "1.0.3",
1843+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
1844+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
1845+ "dev": true,
1846+ "requires": {
1847+ "minipass": "^3.0.0"
1848+ }
1849+ },
1850+ "minizlib": {
1851+ "version": "2.1.2",
1852+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
1853+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
1854+ "dev": true,
1855+ "requires": {
1856+ "minipass": "^3.0.0",
1857+ "yallist": "^4.0.0"
1858+ }
1859+ },
1860+ "mkdirp": {
1861+ "version": "1.0.4",
1862+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
1863+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
1864+ "dev": true
1865+ },
1866+ "mkdirp-classic": {
1867+ "version": "0.5.3",
1868+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
1869+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
1870+ "dev": true
1871+ },
1872+ "ms": {
1873+ "version": "2.1.2",
1874+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1875+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
1876+ "dev": true
1877+ },
1878+ "negotiator": {
1879+ "version": "0.6.3",
1880+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
1881+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
1882+ "dev": true
1883+ },
1884+ "node-fetch": {
1885+ "version": "2.6.1",
1886+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
1887+ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
1888+ "dev": true
1889+ },
1890+ "once": {
1891+ "version": "1.4.0",
1892+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1893+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
1894+ "dev": true,
1895+ "requires": {
1896+ "wrappy": "1"
1897+ }
1898+ },
1899+ "p-limit": {
1900+ "version": "2.3.0",
1901+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
1902+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
1903+ "dev": true,
1904+ "requires": {
1905+ "p-try": "^2.0.0"
1906+ }
1907+ },
1908+ "p-map": {
1909+ "version": "4.0.0",
1910+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
1911+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
1912+ "dev": true,
1913+ "requires": {
1914+ "aggregate-error": "^3.0.0"
1915+ }
1916+ },
1917+ "p-try": {
1918+ "version": "2.2.0",
1919+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
1920+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
1921+ "dev": true
1922+ },
1923+ "path-is-absolute": {
1924+ "version": "1.0.1",
1925+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1926+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
1927+ "dev": true
1928+ },
1929+ "pend": {
1930+ "version": "1.2.0",
1931+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
1932+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
1933+ "dev": true
1934+ },
1935+ "pkg-dir": {
1936+ "version": "4.2.0",
1937+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
1938+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
1939+ "dev": true,
1940+ "requires": {
1941+ "find-up": "^4.0.0"
1942+ },
1943+ "dependencies": {
1944+ "find-up": {
1945+ "version": "4.1.0",
1946+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
1947+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
1948+ "dev": true,
1949+ "requires": {
1950+ "locate-path": "^5.0.0",
1951+ "path-exists": "^4.0.0"
1952+ }
1953+ },
1954+ "locate-path": {
1955+ "version": "5.0.0",
1956+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
1957+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
1958+ "dev": true,
1959+ "requires": {
1960+ "p-locate": "^4.1.0"
1961+ }
1962+ },
1963+ "p-locate": {
1964+ "version": "4.1.0",
1965+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
1966+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
1967+ "dev": true,
1968+ "requires": {
1969+ "p-limit": "^2.2.0"
1970+ }
1971+ },
1972+ "path-exists": {
1973+ "version": "4.0.0",
1974+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
1975+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
1976+ "dev": true
1977+ }
1978+ }
1979+ },
1980+ "progress": {
1981+ "version": "2.0.3",
1982+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
1983+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
1984+ "dev": true
1985+ },
1986+ "promise-inflight": {
1987+ "version": "1.0.1",
1988+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
1989+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
1990+ "dev": true
1991+ },
1992+ "promise-retry": {
1993+ "version": "2.0.1",
1994+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
1995+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
1996+ "dev": true,
1997+ "requires": {
1998+ "err-code": "^2.0.2",
1999+ "retry": "^0.12.0"
2000+ }
2001+ },
2002+ "proxy-from-env": {
2003+ "version": "1.1.0",
2004+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
2005+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
2006+ "dev": true
2007+ },
2008+ "pump": {
2009+ "version": "3.0.0",
2010+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
2011+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
2012+ "dev": true,
2013+ "requires": {
2014+ "end-of-stream": "^1.1.0",
2015+ "once": "^1.3.1"
2016+ }
2017+ },
2018+ "punycode": {
2019+ "version": "2.1.1",
2020+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
2021+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
2022+ },
2023+ "puppeteer": {
2024+ "version": "8.0.0",
2025+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-8.0.0.tgz",
2026+ "integrity": "sha512-D0RzSWlepeWkxPPdK3xhTcefj8rjah1791GE82Pdjsri49sy11ci/JQsAO8K2NRukqvwEtcI+ImP5F4ZiMvtIQ==",
2027+ "dev": true,
2028+ "requires": {
2029+ "debug": "^4.1.0",
2030+ "devtools-protocol": "0.0.854822",
2031+ "extract-zip": "^2.0.0",
2032+ "https-proxy-agent": "^5.0.0",
2033+ "node-fetch": "^2.6.1",
2034+ "pkg-dir": "^4.2.0",
2035+ "progress": "^2.0.1",
2036+ "proxy-from-env": "^1.1.0",
2037+ "rimraf": "^3.0.2",
2038+ "tar-fs": "^2.0.0",
2039+ "unbzip2-stream": "^1.3.3",
2040+ "ws": "^7.2.3"
2041+ },
2042+ "dependencies": {
2043+ "ws": {
2044+ "version": "7.4.4",
2045+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz",
2046+ "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==",
2047+ "dev": true,
2048+ "requires": {}
2049+ }
2050+ }
2051+ },
2052+ "retry": {
2053+ "version": "0.12.0",
2054+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
2055+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
2056+ "dev": true
2057+ },
2058+ "rimraf": {
2059+ "version": "3.0.2",
2060+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
2061+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
2062+ "dev": true,
2063+ "requires": {
2064+ "glob": "^7.1.3"
2065+ }
2066+ },
2067+ "safe-buffer": {
2068+ "version": "5.2.1",
2069+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
2070+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
2071+ "dev": true
2072+ },
2073+ "safer-buffer": {
2074+ "version": "2.1.2",
2075+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
2076+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
2077+ "dev": true,
2078+ "optional": true
2079+ },
2080+ "semver": {
2081+ "version": "7.3.7",
2082+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
2083+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
2084+ "dev": true,
2085+ "requires": {
2086+ "lru-cache": "^6.0.0"
2087+ }
2088+ },
2089+ "smart-buffer": {
2090+ "version": "4.2.0",
2091+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
2092+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
2093+ "dev": true
2094+ },
2095+ "socks": {
2096+ "version": "2.7.0",
2097+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz",
2098+ "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==",
2099+ "dev": true,
2100+ "requires": {
2101+ "ip": "^2.0.0",
2102+ "smart-buffer": "^4.2.0"
2103+ }
2104+ },
2105+ "socks-proxy-agent": {
2106+ "version": "6.2.1",
2107+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz",
2108+ "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==",
2109+ "dev": true,
2110+ "requires": {
2111+ "agent-base": "^6.0.2",
2112+ "debug": "^4.3.3",
2113+ "socks": "^2.6.2"
2114+ }
2115+ },
2116+ "spago": {
2117+ "version": "0.20.9",
2118+ "resolved": "https://registry.npmjs.org/spago/-/spago-0.20.9.tgz",
2119+ "integrity": "sha512-r5TUxnYn9HawlQyMswlhIk24BGFSN2KGbqgZFZrn47GjTpMscU14xkt9CqTWgoSQYsoZieG+3dUtOxUQ7GYD7w==",
2120+ "dev": true,
2121+ "requires": {
2122+ "make-fetch-happen": "^9.1.0",
2123+ "tar": "^6.1.11"
2124+ }
2125+ },
2126+ "ssri": {
2127+ "version": "8.0.1",
2128+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
2129+ "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
2130+ "dev": true,
2131+ "requires": {
2132+ "minipass": "^3.1.1"
2133+ }
2134+ },
2135+ "string_decoder": {
2136+ "version": "1.3.0",
2137+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
2138+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
2139+ "dev": true,
2140+ "requires": {
2141+ "safe-buffer": "~5.2.0"
2142+ }
2143+ },
2144+ "tar": {
2145+ "version": "6.1.11",
2146+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
2147+ "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
2148+ "dev": true,
2149+ "requires": {
2150+ "chownr": "^2.0.0",
2151+ "fs-minipass": "^2.0.0",
2152+ "minipass": "^3.0.0",
2153+ "minizlib": "^2.1.1",
2154+ "mkdirp": "^1.0.3",
2155+ "yallist": "^4.0.0"
2156+ },
2157+ "dependencies": {
2158+ "chownr": {
2159+ "version": "2.0.0",
2160+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
2161+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
2162+ "dev": true
2163+ }
2164+ }
2165+ },
2166+ "tar-fs": {
2167+ "version": "2.1.1",
2168+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
2169+ "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
2170+ "dev": true,
2171+ "requires": {
2172+ "chownr": "^1.1.1",
2173+ "mkdirp-classic": "^0.5.2",
2174+ "pump": "^3.0.0",
2175+ "tar-stream": "^2.1.4"
2176+ }
2177+ },
2178+ "tar-stream": {
2179+ "version": "2.2.0",
2180+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
2181+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
2182+ "dev": true,
2183+ "requires": {
2184+ "bl": "^4.0.3",
2185+ "end-of-stream": "^1.4.1",
2186+ "fs-constants": "^1.0.0",
2187+ "inherits": "^2.0.3",
2188+ "readable-stream": "^3.1.1"
2189+ },
2190+ "dependencies": {
2191+ "readable-stream": {
2192+ "version": "3.6.0",
2193+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
2194+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
2195+ "dev": true,
2196+ "requires": {
2197+ "inherits": "^2.0.3",
2198+ "string_decoder": "^1.1.1",
2199+ "util-deprecate": "^1.0.1"
2200+ }
2201+ }
2202+ }
2203+ },
2204+ "through": {
2205+ "version": "2.3.8",
2206+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
2207+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
2208+ "dev": true
2209+ },
2210+ "uc.micro": {
2211+ "version": "1.0.6",
2212+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
2213+ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
2214+ "dev": true
2215+ },
2216+ "unbzip2-stream": {
2217+ "version": "1.4.3",
2218+ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
2219+ "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
2220+ "dev": true,
2221+ "requires": {
2222+ "buffer": "^5.2.1",
2223+ "through": "^2.3.8"
2224+ },
2225+ "dependencies": {
2226+ "buffer": {
2227+ "version": "5.7.1",
2228+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
2229+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
2230+ "dev": true,
2231+ "requires": {
2232+ "base64-js": "^1.3.1",
2233+ "ieee754": "^1.1.13"
2234+ }
2235+ }
2236+ }
2237+ },
2238+ "unique-filename": {
2239+ "version": "1.1.1",
2240+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
2241+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
2242+ "dev": true,
2243+ "requires": {
2244+ "unique-slug": "^2.0.0"
2245+ }
2246+ },
2247+ "unique-slug": {
2248+ "version": "2.0.2",
2249+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
2250+ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
2251+ "dev": true,
2252+ "requires": {
2253+ "imurmurhash": "^0.1.4"
2254+ }
2255+ },
2256+ "util-deprecate": {
2257+ "version": "1.0.2",
2258+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
2259+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
2260+ "dev": true
2261+ },
2262+ "wrappy": {
2263+ "version": "1.0.2",
2264+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
2265+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
2266+ "dev": true
2267+ },
2268+ "yallist": {
2269+ "version": "4.0.0",
2270+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
2271+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
2272+ "dev": true
2273+ },
2274+ "yauzl": {
2275+ "version": "2.10.0",
2276+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
2277+ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
2278+ "dev": true,
2279+ "requires": {
2280+ "buffer-crc32": "~0.2.3",
2281+ "fd-slicer": "~1.1.0"
2282+ }
2283+ }
2284+ }
2285+}
package.json+23−20
@@ -1,37 +1,37 @@
11{
22 "name": "purescript-docs-search",
3− "version": "0.0.8",
3+ "type": "module",
4+ "version": "0.0.12",
45 "description": "Search frontend for the documentation generated by the PureScript compiler.",
56 "directories": {
67 "test": "test"
78 },
89 "bin": {
9− "purescript-docs-search": "dist/purescript-docs-search"
10+ "purescript-docs-search": "dist/purescript-docs-search.cjs"
1011 },
1112 "files": [
12− "dist/purescript-docs-search",
13+ "dist/purescript-docs-search.cjs",
1314 "dist/docs-search-app.js",
1415 "README.md",
1516 "CHANGELOG.md"
1617 ],
1718 "scripts": {
18− "test": "spago test && npm run check-version",
19+ "test": "spago docs --no-search && ./dist/purescript-docs-search.cjs build-index && spago test && npm run check-version",
1920 "bundle-app": "spago bundle-app --no-build --no-install -m Docs.Search.App --to dist/docs-search-app.js",
20− "parcel-app": "parcel build --no-source-maps --target browser --out-file dist/docs-search-app.js dist/docs-search-app.js",
21− "build-app": "npm run bundle-app && npm run parcel-app",
22− "bundle-main": "spago bundle-app --no-build --no-install -m Docs.Search.Main --to dist/main.js",
23− "parcel-main": "parcel build --no-source-maps --target node --bundle-node-modules --out-file dist/main.js dist/main.js",
24− "add-shebang": "echo \"#!/usr/bin/env node\" > dist/purescript-docs-search && cat dist/main.js >> dist/purescript-docs-search",
25− "chmod-main": "chmod +x dist/purescript-docs-search",
26− "build-main": "npm run bundle-main && npm run parcel-main && npm run add-shebang && rm dist/main.js && npm run chmod-main",
21+ "esbuild-app": "esbuild dist/docs-search-app.js --target=es2016 --bundle --minify --outfile=dist/docs-search-app.min.js && mv dist/docs-search-app.min.js dist/docs-search-app.js",
22+ "build-app": "npm run bundle-app && npm run esbuild-app",
23+ "bundle-main": "spago bundle-app --no-build --no-install --platform node -m Docs.Search.Main --to dist/main.js",
24+ "esbuild-main": "esbuild dist/main.js --platform=node --bundle --minify --outfile=dist/main.min.js && mv dist/main.min.js dist/main.js",
25+ "add-shebang": "echo \"#!/usr/bin/env node\" > dist/purescript-docs-search.cjs && cat dist/main.js >> dist/purescript-docs-search.cjs",
26+ "chmod-main": "chmod +x dist/purescript-docs-search.cjs",
27+ "build-main": "npm run bundle-main && npm run esbuild-main && npm run add-shebang && rm dist/main.js && npm run chmod-main",
2728 "build": "spago build && npm run build-app && npm run build-main",
28− "build-dev": "spago build && npm run build-app && npm run bundle-main && npm run add-shebang && rm dist/main.js && npm run chmod-main",
2929 "clean": "rm -rf dist",
30− "check-version": "[ \"$(./dist/purescript-docs-search version)\" = \"$npm_package_version\" ]"
30+ "check-version": "[ \"$(./dist/purescript-docs-search.cjs version)\" = \"$npm_package_version\" ]"
3131 },
3232 "repository": {
3333 "type": "git",
34− "url": "git+https://github.com/spacchetti/purescript-docs-search.git"
34+ "url": "git+https://github.com/purescript/purescript-docs-search.git"
3535 },
3636 "keywords": [
3737 "purescript"
@@ -39,14 +39,17 @@
3939 "author": "Kalnitsky Vladimir <klntsky@gmail.com>",
4040 "license": "BSD-3-Clause",
4141 "bugs": {
42− "url": "https://github.com/spacchetti/purescript-docs-search/issues"
42+ "url": "https://github.com/purescript/purescript-docs-search/issues"
43+ },
44+ "homepage": "https://github.com/purescript/purescript-docs-search#readme",
45+ "dependencies": {
46+ "punycode": "^2.1.1"
4347 },
44− "homepage": "https://github.com/spacchetti/purescript-docs-search#readme",
45− "dependencies": {},
4648 "devDependencies": {
49+ "esbuild": "^0.11.10",
4750 "glob": "^7.1.6",
48− "markdown-it": "^11.0.0",
49− "parcel": "^1.12.4",
50− "spago": "^0.15.3"
51+ "markdown-it": "^12.0.4",
52+ "puppeteer": "^8.0.0",
53+ "spago": "^0.20.9"
5154 }
5255}
packages.dhall+114−26
@@ -1,10 +1,12 @@
11let mkPackage =
2− https://raw.githubusercontent.com/purescript/package-sets/psc-0.13.2-20190725/src/mkPackage.dhall sha256:0b197efa1d397ace6eb46b243ff2d73a3da5638d8d0ac8473e8e4a8fc528cf57
2+ https://raw.githubusercontent.com/purescript/package-sets/psc-0.13.2-20190725/src/mkPackage.dhall
3+ sha256:0b197efa1d397ace6eb46b243ff2d73a3da5638d8d0ac8473e8e4a8fc528cf57
34
45let upstream =
5− https://github.com/purescript/package-sets/releases/download/psc-0.13.8/packages.dhall sha256:0e95ec11604dc8afc1b129c4d405dcc17290ce56d7d0665a0ff15617e32bbf03
6+ https://github.com/purescript/package-sets/releases/download/psc-0.15.4-20220829/packages.dhall
7+ sha256:9ec64ed24ec308770ccdd3d0edb74a814fcfbe34c7df5c28266935f0b5e585d7
68
7−let overrides = { metadata = upstream.metadata // { version = "v0.13.0" } }
9+let overrides = {=}
810
911let additions =
1012 { halogen =
@@ -13,12 +15,13 @@ let additions =
1315 , "avar"
1416 , "console"
1517 , "const"
16− , "coroutines"
1718 , "dom-indexed"
19+ , "effect"
1820 , "foreign"
1921 , "fork"
2022 , "free"
2123 , "freeap"
24+ , "halogen-subscriptions"
2225 , "halogen-vdom"
2326 , "media-types"
2427 , "nullable"
@@ -28,15 +31,24 @@ let additions =
2831 , "transformers"
2932 , "unsafe-coerce"
3033 , "unsafe-reference"
34+ , "web-file"
3135 , "web-uievents"
3236 ]
33− "https://github.com/slamdata/purescript-halogen.git"
34− "v5.0.0-rc.6"
35− , halogen-css =
37+ "https://github.com/purescript-halogen/purescript-halogen.git"
38+ "v7.0.0"
39+ , memoize =
3640 mkPackage
37− [ "css", "halogen" ]
38− "https://github.com/slamdata/purescript-halogen-css.git"
39− "v8.0.0"
41+ [ "prelude"
42+ , "lazy"
43+ , "either"
44+ , "maybe"
45+ , "tuples"
46+ , "integers"
47+ , "lists"
48+ , "strings"
49+ ]
50+ "https://github.com/paf31/purescript-memoize.git"
51+ "9960694e82adc212fd89f8ed8778cf55fcb72aeb"
4052 , optparse =
4153 mkPackage
4254 [ "prelude"
@@ -46,14 +58,14 @@ let additions =
4658 , "ordered-collections"
4759 , "arrays"
4860 , "console"
49− , "memoize"
5061 , "transformers"
5162 , "exists"
5263 , "node-process"
5364 , "free"
65+ , "memoize"
5466 ]
55− "https://github.com/f-o-a-m/purescript-optparse.git"
56− "v3.0.1"
67+ "https://github.com/klntsky/purescript-optparse.git"
68+ "2fe4265b7c6b09744c11190a43ca06777c752473"
5769 , exitcodes =
5870 mkPackage
5971 [ "enums" ]
@@ -62,33 +74,109 @@ let additions =
6274 , markdown-it =
6375 mkPackage
6476 [ "prelude", "effect", "options" ]
65− "https://github.com/nonbili/purescript-markdown-it.git"
66− "v0.4.0"
77+ "https://github.com/klntsky/purescript-markdown-it.git"
78+ "f3b7654783a83a80d7c09b6caaa7cd40b93ddce1"
79+ , string-parsers =
80+ mkPackage
81+ [ "arrays"
82+ , "assert"
83+ , "bifunctors"
84+ , "console"
85+ , "control"
86+ , "effect"
87+ , "either"
88+ , "enums"
89+ , "foldable-traversable"
90+ , "lists"
91+ , "maybe"
92+ , "minibench"
93+ , "nonempty"
94+ , "partial"
95+ , "prelude"
96+ , "strings"
97+ , "tailrec"
98+ , "transformers"
99+ , "unfoldable"
100+ ]
101+ "https://github.com/purescript-contrib/purescript-string-parsers.git"
102+ "v8.0.0"
67103 , html-parser-halogen =
68104 mkPackage
69− [ "string-parsers", "generics-rep", "halogen" ]
105+ [ "string-parsers", "halogen" ]
70106 "https://github.com/rnons/purescript-html-parser-halogen.git"
71− "890da763cdd2a1049ab8837e477c5ba1fcf6d4ce"
107+ "035a51d02ba9f8b70c3ffd9fe31a3f5bed19941c"
72108 , markdown-it-halogen =
73109 mkPackage
74110 [ "markdown-it", "html-parser-halogen" ]
75111 "https://github.com/nonbili/purescript-markdown-it-halogen.git"
76112 "08c9625015bf04214be14e45230e8ce12f3fa2bf"
77− , bower-json =
113+ , search-trie =
78114 mkPackage
79115 [ "prelude"
80− , "generics-rep"
81− , "maybe"
82116 , "arrays"
83− , "either"
84− , "newtype"
85− , "tuples"
117+ , "ordered-collections"
118+ , "lists"
86119 , "foldable-traversable"
87− , "argonaut-codecs"
120+ , "bifunctors"
121+ ]
122+ "https://github.com/klntsky/purescript-search-trie.git"
123+ "e7f7f22486a1dba22171ec885dbc2149dc815119"
124+ , css =
125+ mkPackage
126+ [ "colors"
127+ , "console"
128+ , "effect"
129+ , "exceptions"
130+ , "nonempty"
131+ , "profunctor"
132+ , "psci-support"
133+ , "strings"
134+ , "these"
135+ , "transformers"
136+ ]
137+ "https://github.com/purescript-contrib/purescript-css.git"
138+ "710d6a742beb88299faf08aaeb997ee1e24483ab"
139+ , jest =
140+ mkPackage
141+ [ "aff"
142+ , "aff-promise"
143+ , "effect"
144+ , "prelude"
145+ , "psci-support"
146+ , "foldable-traversable"
147+ ]
148+ "https://github.com/klntsky/purescript-jest.git"
149+ "7feaa5a880fc75002c4eca312993174e7220252b"
150+ , literals =
151+ mkPackage
152+ [ "assert"
153+ , "effect"
154+ , "console"
155+ , "integers"
156+ , "numbers"
157+ , "partial"
158+ , "psci-support"
159+ , "unsafe-coerce"
160+ , "typelevel-prelude"
161+ ]
162+ "https://github.com/jvliwanag/purescript-literals.git"
163+ "ae3ef4e9c1ae7c57ec77bd13906fa60ae8abba4a"
164+ , untagged-union =
165+ mkPackage
166+ [ "assert"
167+ , "console"
168+ , "effect"
169+ , "foreign"
88170 , "foreign-object"
171+ , "literals"
172+ , "maybe"
173+ , "newtype"
174+ , "psci-support"
175+ , "tuples"
176+ , "unsafe-coerce"
89177 ]
90− "https://github.com/klntsky/purescript-bower-json.git"
91− "v1.0.0"
178+ "https://github.com/jvliwanag/purescript-untagged-union.git"
179+ "ed8262a966e15e751322c327e2759a9b9c0ef3f3"
92180 }
93181
94182in upstream // overrides // additions
release.shnew file+24
@@ -0,0 +1,24 @@
1+#!/usr/bin/env bash
2+
3+set -euo pipefail
4+
5+# Please use this script to cut new releases.
6+# It will create a tag and push it, which will trigger CI to create a release,
7+# build release files, push them to the release, and publish a new version on NPM
8+
9+NEW_TAG=v$(jq -r ".version" package.json)
10+
11+# Fail if the new tag already exists
12+if git rev-parse "${NEW_TAG}" >/dev/null 2>&1; then
13+ echo "Tag '${NEW_TAG}' already exists, please bump the version in package.json";
14+ exit 1;
15+fi
16+
17+echo "Creating and pushing new tag '${NEW_TAG}'.."
18+
19+git tag "${NEW_TAG}"
20+
21+git push origin "${NEW_TAG}"
22+
23+echo "Done."
24+
spago.dhall+53−41
@@ -1,43 +1,55 @@
1−{ sources =
2− [ "src/**/*.purs", "test/**/*.purs" ]
3−, name =
4− "docs-search"
1+{ sources = [ "src/**/*.purs", "test/**/*.purs" ]
2+, name = "docs-search"
53, dependencies =
6− [ "aff-promise"
7− , "argonaut-codecs"
8− , "argonaut-core"
9− , "argonaut-generic"
10− , "arrays"
11− , "bower-json"
12− , "console"
13− , "control"
14− , "coroutines"
15− , "effect"
16− , "foldable-traversable"
17− , "generics-rep"
18− , "halogen"
19− , "halogen-css"
20− , "lists"
21− , "markdown-it"
22− , "markdown-it-halogen"
23− , "maybe"
24− , "newtype"
25− , "node-buffer"
26− , "node-fs"
27− , "node-fs-aff"
28− , "node-process"
29− , "node-readline"
30− , "optparse"
31− , "profunctor"
32− , "profunctor-lenses"
33− , "search-trie"
34− , "string-parsers"
35− , "strings"
36− , "test-unit"
37− , "web-dom"
38− , "web-html"
39− , "web-storage"
40− ]
41−, packages =
42− ./packages.dhall
4+ [ "aff"
5+ , "aff-promise"
6+ , "argonaut-codecs"
7+ , "argonaut-core"
8+ , "argonaut-generic"
9+ , "arrays"
10+ , "bower-json"
11+ , "console"
12+ , "control"
13+ , "css"
14+ , "effect"
15+ , "either"
16+ , "exceptions"
17+ , "foldable-traversable"
18+ , "foreign-object"
19+ , "halogen"
20+ , "halogen-css"
21+ , "halogen-subscriptions"
22+ , "identity"
23+ , "js-uri"
24+ , "lists"
25+ , "markdown-it"
26+ , "markdown-it-halogen"
27+ , "maybe"
28+ , "newtype"
29+ , "node-buffer"
30+ , "node-fs"
31+ , "node-fs-aff"
32+ , "node-process"
33+ , "node-readline"
34+ , "optparse"
35+ , "ordered-collections"
36+ , "parallel"
37+ , "partial"
38+ , "prelude"
39+ , "profunctor"
40+ , "profunctor-lenses"
41+ , "search-trie"
42+ , "spec"
43+ , "string-parsers"
44+ , "strings"
45+ , "transformers"
46+ , "tuples"
47+ , "unfoldable"
48+ , "web-dom"
49+ , "web-events"
50+ , "web-html"
51+ , "web-storage"
52+ , "web-uievents"
53+ ]
54+, packages = ./packages.dhall
4355}
src/Docs/Search/App.purs+54−39
@@ -1,29 +1,33 @@
11-- | This is the main module of the client-side Halogen app.
22module Docs.Search.App where
33
4+import Docs.Search.App.SearchField as SearchField
5+import Docs.Search.App.SearchResults as SearchResults
6+import Docs.Search.App.Sidebar as Sidebar
7+import Docs.Search.Config as Config
8+import Docs.Search.Extra (whenJust)
9+import Docs.Search.ModuleIndex as ModuleIndex
10+import Docs.Search.PackageIndex as PackageIndex
11+import Docs.Search.Meta as Meta
12+
413import Prelude
514
615import Control.Alt (alt)
7−import Control.Coroutine as Coroutine
816import Data.Maybe (Maybe(..))
917import Data.Newtype (wrap)
18+import Data.Map as Map
1019import Data.Tuple (Tuple(..))
1120import Data.Tuple.Nested ((/\))
12−import Docs.Search.App.SearchField as SearchField
13−import Docs.Search.App.SearchResults as SearchResults
14−import Docs.Search.App.Sidebar as Sidebar
15−import Docs.Search.Config (config)
16−import Docs.Search.Extra (whenJust)
17−import Docs.Search.ModuleIndex as ModuleIndex
18−import Docs.Search.PackageIndex as PackageIndex
1921import Effect (Effect)
2022import Effect.Aff (launchAff_)
2123import Halogen as H
2224import Halogen.Aff as HA
25+import Halogen.Subscription (subscribe)
2326import Halogen.VDom.Driver (runUI)
2427import MarkdownIt as MD
2528import Web.DOM.ChildNode as ChildNode
2629import Web.DOM.Document as Document
30+import Web.DOM.Document (Document)
2731import Web.DOM.Element as Element
2832import Web.DOM.Node as Node
2933import Web.DOM.ParentNode as ParentNode
@@ -39,12 +43,11 @@ import Web.HTML.Window as Window
3943
4044main :: Effect Unit
4145main = do
42− win <- HTML.window
43− doc <- HTMLDocument.toDocument <$> Window.document win
46+ window <- HTML.window
4447
45− insertStyle doc
46− insertVersionInfo doc
47− mbContainers <- getContainers doc
48+ insertStyle
49+ insertVersionInfo
50+ mbContainers <- getContainers
4851
4952 -- Initialize a `markdown-it` instance (we need it to render the docs as markdown)
5053 markdownIt <- MD.newMarkdownIt MD.Default mempty
@@ -63,55 +66,62 @@ main = do
6366 HA.runHalogenAff do
6467 packageIndex <- PackageIndex.loadPackageIndex
6568 moduleIndex <- ModuleIndex.unpackModuleIndex <$> ModuleIndex.loadModuleIndex
69+ meta <- Meta.load
6670 let scores = PackageIndex.mkScoresFromPackageIndex packageIndex
6771
6872 let initialSearchEngineState = { packageIndex
6973 , moduleIndex
70− , index: mempty
71− , typeIndex: mempty
74+ , index: wrap Map.empty
75+ , typeIndex: wrap Map.empty
7276 , scores
7377 }
74−
7578 resultsComponent =
76− SearchResults.mkComponent initialSearchEngineState pageContents markdownIt
79+ SearchResults.mkComponent
80+ initialSearchEngineState
81+ pageContents
82+ markdownIt
83+ meta
7784
7885 sfio <- runUI SearchField.component unit searchField
7986 srio <- runUI resultsComponent unit searchResults
8087
81− sfio.subscribe $
82− Coroutine.consumer (srio.query <<< H.tell <<< SearchResults.MessageFromSearchField)
88+ void $ H.liftEffect $ subscribe sfio.messages $ \sfm -> do
89+ launchAff_ $ void do
90+ srio.query (SearchResults.MessageFromSearchField sfm unit)
8391
8492 -- We need to read the URI hash only when both components are initialized and
8593 -- the search field is subscribed to the main component.
86− void $ sfio.query $ H.tell SearchField.ReadURIHash
94+ void $ sfio.query $ SearchField.ReadURIHash unit
8795
8896 -- Subscribe to URI hash updates
8997 H.liftEffect do
9098
9199 listener <-
92− eventListener \event ->
93− launchAff_ do
94− sfio.query $ H.tell SearchField.ReadURIHash
100+ eventListener \_event ->
101+ launchAff_ $ void do
102+ sfio.query $ SearchField.ReadURIHash unit
95103
96− addEventListener hashchange listener true (Window.toEventTarget win)
104+ addEventListener hashchange listener true (Window.toEventTarget window)
97105
98106 sbio <- do
99− component <- Sidebar.mkComponent moduleIndex.packageModules isIndexHTML
100− runUI component unit sidebarContainer
107+ component <- Sidebar.mkComponent moduleIndex isIndexHTML meta
108+ runUI component unit sidebarContainer
101109
102110 -- Subscribe to window focus events
103111 H.liftEffect do
104112
105113 listener <-
106− eventListener \event ->
107− launchAff_ do
108− sbio.query $ H.tell Sidebar.UpdateModuleGrouping
114+ eventListener \_event ->
115+ launchAff_ $ void do
116+ sbio.query $ Sidebar.UpdateModuleGrouping unit
117+
118+ addEventListener focus listener true (Window.toEventTarget window)
109119
110− addEventListener focus listener true (Window.toEventTarget win)
111120
121+insertStyle :: Effect Unit
122+insertStyle = do
123+ doc <- getDocument
112124
113−insertStyle :: Document.Document -> Effect Unit
114−insertStyle doc = do
115125 let styleContents = """
116126 .top-banner__actions {
117127 width: 10%;
@@ -176,8 +186,9 @@ insertStyle doc = do
176186 void $ Node.appendChild (Element.toNode style) (Element.toNode head)
177187
178188
179−insertVersionInfo :: Document.Document -> Effect Unit
180−insertVersionInfo doc = do
189+insertVersionInfo :: Effect Unit
190+insertVersionInfo = do
191+ doc <- getDocument
181192 let docPN = Document.toParentNode doc
182193 mbVersionInfo <-
183194 ParentNode.querySelector (wrap ".footer > p") docPN
@@ -186,10 +197,10 @@ insertVersionInfo doc = do
186197 prefix <- Document.createTextNode " - patched by " doc <#> Text.toNode
187198 linkElement <- Document.createElement "a" doc
188199 let linkNode = Element.toNode linkElement
189− Element.setAttribute "href" "https://github.com/spacchetti/purescript-docs-search" linkElement
200+ Element.setAttribute "href" "https://github.com/purescript/purescript-docs-search" linkElement
190201 Element.setAttribute "target" "_blank" linkElement
191202 linkText <- Document.createTextNode ("docs-search") doc <#> Text.toNode
192− suffix <- Document.createTextNode (" " <> config.version) doc <#> Text.toNode
203+ suffix <- Document.createTextNode (" " <> Config.version) doc <#> Text.toNode
193204 void $ Node.appendChild prefix versionInfo
194205 void $ Node.appendChild linkNode versionInfo
195206 void $ Node.appendChild linkText linkNode
@@ -199,15 +210,15 @@ insertVersionInfo doc = do
199210-- | Query the DOM for specific elements that should always be present and determine if we are on
200211-- | `index.html` or not.
201212getContainers
202− :: Document.Document
203− -> Effect (Maybe { searchField :: HTML.HTMLElement
213+ :: Effect (Maybe { searchField :: HTML.HTMLElement
204214 , searchResults :: HTML.HTMLElement
205215 , pageContents :: Element.Element
206216 , sidebarContainer :: HTML.HTMLElement
207217 , realSidebar :: Element.Element
208218 , isIndexHTML :: Sidebar.IsIndexHTML
209219 })
210−getContainers doc = do
220+getContainers = do
221+ doc <- getDocument
211222 let docPN = Document.toParentNode doc
212223 mbBanner <-
213224 ParentNode.querySelector (wrap ".top-banner > .container") docPN
@@ -243,3 +254,7 @@ getContainers doc = do
243254 , isIndexHTML
244255 }
245256 | otherwise -> pure Nothing
257+
258+
259+getDocument :: Effect Document
260+getDocument = HTML.window >>= map HTMLDocument.toDocument <<< Window.document
src/Docs/Search/App/SearchField.purs+11−10
@@ -15,7 +15,7 @@ import Halogen.HTML as HH
1515import Halogen.HTML.CSS as HS
1616import Halogen.HTML.Events as HE
1717import Halogen.HTML.Properties as HP
18−import Halogen.Query.EventSource as ES
18+import Halogen.Query.Event as ES
1919import Web.DOM.Document as Document
2020import Web.DOM.ParentNode as ParentNode
2121import Web.HTML as HTML
@@ -36,6 +36,7 @@ data Action
3636 | FocusChanged Boolean
3737 | InitKeyboardListener
3838 | HandleKey H.SubscriptionId KeyboardEvent
39+ | NoOp
3940
4041data Query a
4142 = ReadURIHash a
@@ -46,7 +47,7 @@ data SearchFieldMessage
4647 | Focused
4748 | LostFocus
4849
49−component :: forall i. H.Component HH.HTML Query i SearchFieldMessage Aff
50+component :: forall i. H.Component Query i SearchFieldMessage Aff
5051component =
5152 H.mkComponent
5253 { initialState
@@ -73,12 +74,12 @@ initialState _ = { input: "", focused: false }
7374
7475handleAction :: Action -> H.HalogenM State Action () SearchFieldMessage Aff Unit
7576handleAction = case _ of
76−
77+ NoOp -> pure unit
7778 InitKeyboardListener -> do
7879
7980 document <- H.liftEffect $ Window.document =<< HTML.window
8081 H.subscribe' \sid ->
81− ES.eventListenerEventSource
82+ ES.eventListener
8283 KET.keyup
8384 (HTMLDocument.toEventTarget document)
8485 (map (HandleKey sid) <<< KE.fromEvent)
@@ -155,15 +156,15 @@ render state =
155156 [ HH.input
156157 [ HP.value state.input
157158 , HP.placeholder "Search for definitions... (S to focus)"
158− , HP.id_ "docs-search-query-field"
159+ , HP.id "docs-search-query-field"
159160 , HP.type_ HP.InputText
160161 , HE.onKeyUp (\event ->
161162 case KeyboardEvent.code event of
162− "Enter" -> Just EnterPressed
163− _ -> Nothing)
164− , HE.onValueInput (Just <<< InputAction)
165− , HE.onFocusIn $ const $ Just $ FocusChanged true
166− , HE.onFocusOut $ const $ Just $ FocusChanged false
163+ "Enter" -> EnterPressed
164+ _ -> NoOp)
165+ , HE.onValueInput InputAction
166+ , HE.onFocusIn $ const $ FocusChanged true
167+ , HE.onFocusOut $ const $ FocusChanged false
167168 , HS.style do
168169
169170 let pursuitColor = rgb 0x1d 0x22 0x2d
src/Docs/Search/App/SearchResults.purs+86−84
@@ -3,25 +3,27 @@ module Docs.Search.App.SearchResults where
33
44import Docs.Search.App.SearchField (SearchFieldMessage(..))
55import Docs.Search.BrowserEngine (PartialIndex, browserSearchEngine)
6−import Docs.Search.Config (config)
6+import Docs.Search.Config as Config
77import Docs.Search.Declarations (DeclLevel(..), declLevelToHashAnchor)
88import Docs.Search.DocsJson (DataDeclType(..))
9−import Docs.Search.Engine (Result(..))
9+import Docs.Search.Engine (Result(..), packageInfoToString)
1010import Docs.Search.Engine as Engine
1111import Docs.Search.Extra (homePageFromRepository, (>#>))
1212import Docs.Search.ModuleIndex (ModuleResult)
1313import Docs.Search.PackageIndex (PackageResult)
1414import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
15−import Docs.Search.TypeDecoder (Constraint(..), FunDep(..), FunDeps(..), Kind(..), QualifiedName(..), Type(..), TypeArgument(..), joinForAlls, joinRows)
15+import Docs.Search.TypeDecoder (Constraint(..), FunDep(..), FunDeps(..), QualifiedName(..), Type(..), TypeArgument(..), joinForAlls, joinRows)
1616import Docs.Search.TypeIndex (TypeIndex)
17+import Docs.Search.Types (Identifier(..), ModuleName(..), PackageName)
18+import Docs.Search.Meta (Meta)
1719
1820import Prelude
19−
21+import Prim hiding (Type, Constraint)
2022import Data.Array ((!!))
2123import Data.Array as Array
2224import Data.List as List
2325import Data.Maybe (Maybe(..), isJust, fromMaybe)
24−import Data.Newtype (wrap)
26+import Data.Newtype (wrap, unwrap)
2527import Data.String.CodeUnits (stripSuffix) as String
2628import Data.String.Common (null, trim) as String
2729import Data.String.Pattern (Pattern(..)) as String
@@ -55,6 +57,7 @@ type State = { engineState :: EngineState
5557 , resultsCount :: Int
5658 , mode :: Mode
5759 , markdownIt :: MD.MarkdownIt
60+ , localPackageName :: PackageName
5861 }
5962
6063
@@ -63,7 +66,7 @@ data Query a
6366
6467
6568data Action
66− = SearchResultClicked String
69+ = SearchResultClicked ModuleName
6770 | MoreResultsRequested
6871
6972
@@ -72,16 +75,18 @@ mkComponent
7275 . EngineState
7376 -> Element
7477 -> MD.MarkdownIt
75− -> H.Component HH.HTML Query i o Aff
76−mkComponent initialEngineState contents markdownIt =
78+ -> Meta
79+ -> H.Component Query i o Aff
80+mkComponent initialEngineState contents markdownIt { localPackageName } =
7781 H.mkComponent
7882 { initialState: const { engineState: initialEngineState
7983 , results: []
8084 , input: ""
8185 , contents
82− , resultsCount: config.resultsCount
86+ , resultsCount: Config.resultsCount
8387 , mode: Off
8488 , markdownIt
89+ , localPackageName
8590 }
8691 , render
8792 , eval: H.mkEval $ H.defaultEval { handleQuery = handleQuery
@@ -111,7 +116,7 @@ handleQuery (MessageFromSearchField (InputUpdated input_) next) = do
111116 H.modify_ (_ { mode = Off })
112117 showPageContents
113118 else do
114− H.modify_ (_ { mode = Loading, resultsCount = config.resultsCount })
119+ H.modify_ (_ { mode = Loading, resultsCount = Config.resultsCount })
115120
116121 void $ H.fork do
117122 { index, results } <- H.liftAff $
@@ -145,7 +150,7 @@ handleAction = case _ of
145150 location <- Window.location window
146151 pathname <- Location.pathname location
147152 pure $ isJust $
148− String.stripSuffix (String.Pattern $ moduleName <> ".html") pathname
153+ String.stripSuffix (String.Pattern $ unwrap moduleName <> ".html") pathname
149154
150155 when onThisPage do
151156 showPageContents
@@ -190,18 +195,17 @@ render state@{ mode: Active, results: [] } =
190195 , HH.text " did not yield any results."
191196 ]
192197 ]
193−
194198render state@{ mode: Active } =
195199 renderContainer $
196200 [ HH.h1_ [ HH.text "Search results" ]
197201
198202 , HH.div_ $
199− Array.concat $ shownResults <#> renderResult state.markdownIt
203+ Array.concat $ shownResults <#> renderResult state
200204
201− , HH.div [ HP.class_ (wrap "load_more"), HP.id_ "load-more" ]
205+ , HH.div [ HP.class_ (wrap "load_more"), HP.id "load-more" ]
202206 [ if Array.length shownResults < Array.length state.results
203− then HH.a [ HP.id_ "load-more-link"
204− , HE.onClick $ const $ Just MoreResultsRequested ]
207+ then HH.a [ HP.id "load-more-link"
208+ , HE.onClick $ const MoreResultsRequested ]
205209 [ HH.text "Show more results" ]
206210 else HH.p_
207211 [ HH.text "No further results." ]
@@ -210,7 +214,6 @@ render state@{ mode: Active } =
210214 where
211215 shownResults = Array.take state.resultsCount state.results
212216
213−
214217renderContainer :: forall a b. Array (HH.HTML b a) -> HH.HTML b a
215218renderContainer =
216219 HH.div [ HP.classes [ wrap "container", wrap "clearfix" ] ] <<<
@@ -228,13 +231,17 @@ renderSummary text =
228231
229232renderResult
230233 :: forall a
231− . MD.MarkdownIt
234+ . State
232235 -> Result
233236 -> Array (HH.HTML a Action)
234−renderResult markdownIt (DeclResult r) = renderSearchResult markdownIt r
235−renderResult markdownIt (TypeResult r) = renderSearchResult markdownIt r
236−renderResult markdownIt (PackResult r) = renderPackageResult r
237−renderResult markdownIt (MdlResult r) = renderModuleResult r
237+renderResult state (DeclResult r) =
238+ renderSearchResult state r
239+renderResult state (TypeResult r) =
240+ renderSearchResult state r
241+renderResult state (PackResult r) =
242+ renderPackageResult r
243+renderResult state (MdlResult r) =
244+ renderModuleResult r
238245
239246
240247renderPackageResult
@@ -254,7 +261,7 @@ renderPackageResult { name, description, repository } =
254261 , HH.a [ HP.class_ (wrap "result__link")
255262 , HP.href $ fromMaybe "" repository # homePageFromRepository
256263 ]
257− [ HH.text name ]
264+ [ HH.text $ unwrap name ]
258265 ]
259266 ]
260267 ] <>
@@ -280,9 +287,9 @@ renderModuleResult { name, package } =
280287 [ HH.text "M" ]
281288
282289 , HH.a [ HP.class_ (wrap "result__link")
283− , HP.href $ name <> ".html"
290+ , HP.href $ unwrap name <> ".html"
284291 ]
285− [ HH.text name ]
292+ [ HH.text $ unwrap name ]
286293 ]
287294 ]
288295 ]
@@ -290,27 +297,27 @@ renderModuleResult { name, package } =
290297
291298renderSearchResult
292299 :: forall a
293− . MD.MarkdownIt
300+ . State
294301 -> SearchResult
295302 -> Array (HH.HTML a Action)
296−renderSearchResult markdownIt (SearchResult result) =
303+renderSearchResult state (SearchResult result) =
297304 -- class names here and below are from Pursuit.
298305 [ HH.div [ HP.class_ (wrap "result") ]
299306 [ HH.h3 [ HP.class_ (wrap "result__title") ]
300307 [ HH.a [ HP.class_ (wrap "result__link")
301− , HE.onClick $ const $ Just $ SearchResultClicked result.moduleName
308+ , HE.onClick $ const $ SearchResultClicked result.moduleName
302309 , HP.href $
303− result.moduleName <> ".html#" <>
304− result.hashAnchor <> ":" <> result.name
310+ unwrap result.moduleName <> ".html#" <>
311+ result.hashAnchor <> ":" <> unwrap result.name
305312 ]
306− [ HH.text result.name ]
313+ [ HH.text $ unwrap result.name ]
307314 ]
308315 ]
309316
310317 , HH.div [ HP.class_ (wrap "result__body") ] $
311318 renderResultType result <>
312319
313− result.comments >#> pure <<< MDH.render_ markdownIt
320+ result.comments >#> pure <<< MDH.render_ state.markdownIt
314321
315322 , HH.div [ HP.class_ (wrap "result__actions") ]
316323
@@ -321,7 +328,7 @@ renderSearchResult markdownIt (SearchResult result) =
321328 , HP.title "Package"
322329 ]
323330 [ HH.text "P" ]
324− , HH.text result.packageName
331+ , HH.text $ packageInfoToString state.localPackageName result.packageInfo
325332 ]
326333
327334 , HH.span [ HP.class_ (wrap "result__actions__item") ]
@@ -331,7 +338,7 @@ renderSearchResult markdownIt (SearchResult result) =
331338 , HP.title "Module"
332339 ]
333340 [ HH.text "M" ]
334− , HH.text result.moduleName
341+ , HH.text $ unwrap result.moduleName
335342 ]
336343 ]
337344 ]
@@ -340,8 +347,8 @@ renderSearchResult markdownIt (SearchResult result) =
340347renderResultType
341348 :: forall a rest
342349 . { info :: ResultInfo
343− , name :: String
344− , moduleName :: String
350+ , name :: Identifier
351+ , moduleName :: ModuleName
345352 | rest
346353 }
347354 -> Array (HH.HTML a Action)
@@ -371,16 +378,16 @@ renderResultType result =
371378
372379renderValueSignature
373380 :: forall a rest
374− . { moduleName :: String
375− , name :: String
381+ . { moduleName :: ModuleName
382+ , name :: Identifier
376383 | rest
377384 }
378385 -> Type
379386 -> Array (HH.HTML a Action)
380387renderValueSignature result ty =
381388 [ HH.a [ makeHref ValueLevel false result.moduleName result.name
382− , HE.onClick $ const $ Just $ SearchResultClicked result.moduleName ]
383− [ HH.text result.name ]
389+ , HE.onClick $ const $ SearchResultClicked result.moduleName ]
390+ [ HH.text $ unwrap result.name ]
384391 , HH.text " :: "
385392 , renderType ty ]
386393
@@ -391,7 +398,7 @@ renderTypeClassSignature
391398 , arguments :: Array TypeArgument
392399 , superclasses :: Array Constraint
393400 }
394− -> { name :: String, moduleName :: String | rest }
401+ -> { name :: Identifier, moduleName :: ModuleName | rest }
395402 -> Array (HH.HTML a Action)
396403renderTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName } =
397404 [ keyword "class"
@@ -410,10 +417,10 @@ renderTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName
410417 ]
411418 , space
412419 , HH.a [ makeHref TypeLevel false moduleName name
413− , HE.onClick $ const $ Just $
420+ , HE.onClick $ const $
414421 SearchResultClicked moduleName
415422 ]
416− [ HH.text name ]
423+ [ HH.text $ unwrap name ]
417424 , space
418425 ] <> (
419426 Array.intercalate [ space ] $
@@ -443,10 +450,10 @@ renderTypeClassMemberSignature
443450 , typeClass :: QualifiedName
444451 , typeClassArguments :: Array TypeArgument
445452 }
446− -> { name :: String | rest }
453+ -> { name :: Identifier | rest }
447454 -> Array (HH.HTML a Action)
448455renderTypeClassMemberSignature { type: ty, typeClass, typeClassArguments } result =
449− [ HH.text result.name
456+ [ HH.text $ unwrap result.name
450457 , HH.text " :: "
451458 , renderType ty
452459 ]
@@ -456,7 +463,7 @@ renderDataSignature
456463 :: forall a rest
457464 . { typeArguments :: Array TypeArgument
458465 , dataDeclType :: DataDeclType }
459− -> { name :: String | rest }
466+ -> { name :: Identifier | rest }
460467 -> Array (HH.HTML a Action)
461468renderDataSignature { typeArguments, dataDeclType } { name } =
462469 [ keyword
@@ -464,7 +471,7 @@ renderDataSignature { typeArguments, dataDeclType } { name } =
464471 NewtypeDataDecl -> "newtype"
465472 DataDataDecl -> "data"
466473 , space
467− , HH.text name
474+ , HH.text $ unwrap name
468475 , space
469476 , HH.span_ $
470477 Array.intercalate [ space ] $
@@ -477,12 +484,12 @@ renderTypeSynonymSignature
477484 . { type :: Type
478485 , arguments :: Array TypeArgument
479486 }
480− -> { name :: String | rest }
487+ -> { name :: Identifier | rest }
481488 -> Array (HH.HTML a Action)
482489renderTypeSynonymSignature { type: ty, arguments } { name } =
483490 [ keyword "type"
484491 , space
485− , HH.text name
492+ , HH.text $ unwrap name
486493 , space
487494 , HH.span_ $
488495 Array.intercalate [ space ] $
@@ -498,12 +505,12 @@ renderTypeArgument :: forall a. TypeArgument -> Array (HH.HTML a Action)
498505renderTypeArgument (TypeArgument { name, mbKind }) =
499506 case mbKind of
500507 Nothing ->
501− [ HH.text name ]
508+ [ HH.text $ name ]
502509 Just kind ->
503510 [ HH.text "("
504− , HH.text name
511+ , HH.text $ name
505512 , HH.text " :: "
506− , renderKind kind
513+ , renderType kind
507514 , HH.text ")"
508515 ]
509516
@@ -520,15 +527,15 @@ renderType = case _ of
520527 TypeOp qname -> renderQualifiedName true TypeLevel qname
521528
522529 TypeApp (TypeApp (TypeConstructor
523− (QualifiedName { moduleName: [ "Prim" ]
524− , name: "Function" })) t1) t2 ->
530+ (QualifiedName { moduleNameParts: [ "Prim" ]
531+ , name: Identifier "Function" })) t1) t2 ->
525532 HH.span_ [ renderType t1
526533 , syntax " -> "
527534 , renderType t2
528535 ]
529536
530− TypeApp (TypeConstructor (QualifiedName { moduleName: [ "Prim" ]
531− , name: "Record" }))
537+ TypeApp (TypeConstructor (QualifiedName { moduleNameParts: [ "Prim" ]
538+ , name: Identifier "Record" }))
532539 row ->
533540 renderRow false row
534541
@@ -538,6 +545,9 @@ renderType = case _ of
538545 , renderType t2
539546 ]
540547
548+ KindApp t1 t2 ->
549+ HH.span_ [ renderType t1, space, renderType t2 ]
550+
541551 ty@(ForAll _ _ _) ->
542552 renderForAll ty
543553
@@ -551,6 +561,9 @@ renderType = case _ of
551561 ty@REmpty -> renderRow true ty
552562 ty@(RCons _ _ _) -> renderRow true ty
553563
564+ Kinded t1 t2 ->
565+ HH.span_ [ renderType t1, space, syntax "::", space, renderType t2 ]
566+
554567 BinaryNoParensType op t1 t2 ->
555568 HH.span_
556569 [ renderType t1
@@ -585,7 +598,7 @@ renderForAll ty =
585598 HH.span_ [ HH.text $ " (" <> name <> " "
586599 , syntax "::"
587600 , space
588− , renderKind kind
601+ , renderType kind
589602 , HH.text ")" ]
590603 ) <>
591604
@@ -623,7 +636,7 @@ renderRow asRow =
623636
624637 ( Array.intercalate [ HH.text ", " ] $ Array.fromFoldable $ rows <#>
625638 \entry ->
626− [ HH.span_ [ HH.text $ entry.row <> " :: "
639+ [ HH.span_ [ HH.text $ unwrap entry.row <> " :: "
627640 , renderType entry.ty ] ]
628641 ) <>
629642
@@ -635,6 +648,9 @@ renderRow asRow =
635648 opening = if asRow then "( " else "{ "
636649 closing = if asRow then " )" else " }"
637650
651+ primRecord :: QualifiedName
652+ primRecord = QualifiedName { moduleNameParts: [ "Prim" ], name: Identifier "Record" }
653+
638654
639655renderConstraint
640656 :: forall a
@@ -652,28 +668,18 @@ renderQualifiedName
652668 -> DeclLevel
653669 -> QualifiedName
654670 -> HH.HTML a Action
655−renderQualifiedName isInfix level (QualifiedName { moduleName, name })
671+renderQualifiedName isInfix level (QualifiedName { moduleNameParts, name })
656672 = if isBuiltIn then
657− HH.text name
673+ HH.text $ unwrap name
658674 else
659− HH.a [ HE.onClick $ const $ Just $
660− SearchResultClicked moduleNameString
661− , makeHref level isInfix moduleNameString name
675+ HH.a [ HE.onClick $ const $
676+ SearchResultClicked $ moduleName
677+ , makeHref level isInfix moduleName name
662678 ]
663− [ HH.text name ]
679+ [ HH.text $ unwrap name ]
664680 where
665− moduleNameString = Array.intercalate "." moduleName
666− isBuiltIn = moduleName !! 0 == Just "Prim"
667−
668−
669−renderKind
670− :: forall a
671− . Kind
672− -> HH.HTML a Action
673−renderKind = case _ of
674− Row k1 -> HH.span_ [ HH.text "# ", renderKind k1 ]
675− FunKind k1 k2 -> HH.span_ [ renderKind k1, syntax " -> ", renderKind k2 ]
676− NamedKind qname -> renderQualifiedName false KindLevel qname
681+ moduleName = ModuleName $ Array.intercalate "." $ moduleNameParts
682+ isBuiltIn = moduleNameParts !! 0 == Just "Prim"
677683
678684
679685-- | Construct a `href` property value w.r.t. `DeclLevel`.
@@ -681,18 +687,14 @@ makeHref
681687 :: forall t rest
682688 . DeclLevel
683689 -> Boolean
684− -> String
685− -> String
690+ -> ModuleName
691+ -> Identifier
686692 -> HH.IProp ( href :: String | rest ) t
687693makeHref level isInfix moduleName name =
688694 HP.href $
689− moduleName <> ".html#" <>
695+ unwrap moduleName <> ".html#" <>
690696 declLevelToHashAnchor level <> ":" <>
691− if isInfix then "type (" <> name <> ")" else name
692−
693−
694−primRecord :: QualifiedName
695−primRecord = QualifiedName { moduleName: [ "Prim" ], name: "Record" }
697+ if isInfix then "type (" <> unwrap name <> ")" else unwrap name
696698
697699
698700keyword
src/Docs/Search/App/Sidebar.purs+79−31
@@ -1,21 +1,22 @@
11module Docs.Search.App.Sidebar where
22
3−import Docs.Search.Config (config)
4−import Docs.Search.ModuleIndex (PackedModuleIndex)
5−import Docs.Search.Types (ModuleName, PackageName)
3+import Docs.Search.Config as Config
4+import Docs.Search.Meta (Meta)
5+import Docs.Search.ModuleIndex (ModuleIndex)
6+import Docs.Search.Types (ModuleName(..), PackageInfo(..), PackageName)
67
78import Prelude
9+
810import Data.Array as Array
911import Data.Lens ((.~))
1012import Data.Lens.Record (prop)
1113import Data.List (foldr)
1214import Data.Map (Map)
1315import Data.Map as Map
14−import Data.Maybe (Maybe(..), isJust)
15−import Data.Newtype (wrap)
16+import Data.Maybe (Maybe(..), isJust, fromMaybe)
17+import Data.Newtype (wrap, unwrap)
1618import Data.Set (Set)
1719import Data.Set as Set
18−import Data.Symbol (SProxy(..))
1920import Data.Tuple.Nested (type (/\), (/\))
2021import Effect (Effect)
2122import Effect.Aff (Aff)
@@ -23,9 +24,16 @@ import Halogen as H
2324import Halogen.HTML as HH
2425import Halogen.HTML.Events as HE
2526import Halogen.HTML.Properties as HP
27+import Type.Proxy (Proxy(..))
2628import Web.HTML as HTML
2729import Web.HTML.Window as Window
2830import Web.Storage.Storage as Storage
31+import Web.DOM.Document as Document
32+import Web.DOM.Element as Element
33+import Web.HTML.HTMLDocument as HTMLDocument
34+import Web.DOM.ParentNode as ParentNode
35+import Data.Traversable (traverse)
36+import Web.DOM.Node as Node
2937
3038
3139data Action = ToggleGrouping GroupingMode
@@ -42,26 +50,33 @@ data IsIndexHTML = IsIndexHTML | NotIndexHTML
4250
4351derive instance isIndexHTMLEq :: Eq IsIndexHTML
4452
45−type State = { moduleIndex :: Map PackageName (Set ModuleName)
53+type State = { packageModules :: Map PackageInfo (Set ModuleName)
4654 , groupingMode :: GroupingMode
4755 , moduleNames :: Array ModuleName
4856 , isIndexHTML :: IsIndexHTML
57+ , localPackageName :: PackageName
58+ , currentPackage :: PackageInfo
4959 }
5060
5161
5262mkComponent
5363 :: forall i
54− . PackedModuleIndex
64+ . ModuleIndex
5565 -> IsIndexHTML
56− -> Aff (H.Component HH.HTML Query i Action Aff)
57−mkComponent moduleIndex isIndexHTML = do
66+ -> Meta
67+ -> Aff (H.Component Query i Action Aff)
68+mkComponent moduleIndex@{ packageModules } isIndexHTML { localPackageName } = do
5869 groupingMode <- H.liftEffect loadGroupingModeFromLocalStorage
70+ mbModuleName <- H.liftEffect getCurrentModuleName
71+ let currentPackage = getCurrentPackage moduleIndex mbModuleName
5972 pure $
6073 H.mkComponent
61− { initialState: const { moduleIndex
74+ { initialState: const { packageModules
6275 , groupingMode
6376 , moduleNames
6477 , isIndexHTML
78+ , localPackageName
79+ , currentPackage
6580 }
6681 , render
6782 , eval: H.mkEval $ H.defaultEval { handleAction = handleAction
@@ -69,7 +84,9 @@ mkComponent moduleIndex isIndexHTML = do
6984 }
7085 }
7186 where
72− moduleNames = Array.sort $ Array.fromFoldable $ foldr Set.union mempty moduleIndex
87+ moduleNames =
88+ Array.sort $ Array.fromFoldable $
89+ foldr Set.union mempty moduleIndex.packageModules
7390
7491
7592handleAction
@@ -83,9 +100,9 @@ handleAction (ToggleGrouping groupingMode) = do
83100 window <- HTML.window
84101 localStorage <- Window.localStorage window
85102
86− if groupingMode == GroupByPackage
87− then Storage.setItem config.groupModulesItem "true" localStorage
88− else Storage.removeItem config.groupModulesItem localStorage
103+ if groupingMode == DontGroup
104+ then Storage.setItem Config.groupModulesItem "false" localStorage
105+ else Storage.removeItem Config.groupModulesItem localStorage
89106
90107
91108handleQuery
@@ -104,25 +121,25 @@ render
104121 :: forall m
105122 . State
106123 -> H.ComponentHTML Action () m
107−render { moduleIndex, groupingMode, moduleNames, isIndexHTML } =
124+render state@{ groupingMode, moduleNames, localPackageName } =
108125
109126 HH.div [ HP.classes [ wrap "col"
110− , wrap $ if isIndexHTML == IsIndexHTML
127+ , wrap $ if state.isIndexHTML == IsIndexHTML
111128 then "col--main"
112129 else "col--aside"
113130 ]
114131 ]
115132
116− [ HH.h3_ [ HH.text "Modules" ]
117− , HH.input [ HP.id_ "group-modules__input"
133+ [ HH.h3_ [ HH.text $ if groupingMode == DontGroup then "Modules" else "Packages" ]
134+ , HH.input [ HP.id "group-modules__input"
118135 , HP.type_ HP.InputCheckbox
119136 , HP.checked (groupingMode == GroupByPackage)
120− , HE.onChecked $ Just <<< ToggleGrouping <<< isCheckedToGroupingMode
137+ , HE.onChecked $ ToggleGrouping <<< isCheckedToGroupingMode
121138 ]
122139
123140 , HH.text " "
124141 , HH.label [ HP.for "group-modules__input"
125− , HP.id_ "group-modules__label"
142+ , HP.id "group-modules__label"
126143 ]
127144 [ HH.text " GROUP BY PACKAGE" ]
128145
@@ -132,22 +149,37 @@ render { moduleIndex, groupingMode, moduleNames, isIndexHTML } =
132149 ]
133150 where
134151
135− renderPackageEntry (packageName /\ modules) =
152+ renderPackageEntry (package /\ modules) =
136153 HH.li [ HP.classes [ wrap "li-package" ] ]
137− [ HH.details_
138− [ HH.summary_ [ HH.text packageName ]
154+ [ HH.details
155+ (if isCurrentPackage then [ HP.attr (wrap "open") "" ] else [])
156+ [ HH.summary_
157+ [ HH.text $
158+ case package of
159+ Package packageName -> unwrap packageName
160+ LocalPackage -> unwrap localPackageName
161+ Builtin -> "<builtins>"
162+ UnknownPackage -> "<unknown>"
163+ ]
139164 , HH.ul_ $ Set.toUnfoldable modules <#> renderModuleName
140165 ]
141166 ]
167+ where
168+
169+ isCurrentPackage =
170+ state.currentPackage == package &&
171+ -- If we don't know which package we are in, we don't want to expand
172+ -- "Unknown package" section
173+ state.currentPackage /= UnknownPackage
142174
143175 renderModuleName moduleName =
144176 HH.li_
145− [ HH.a [ HP.href (moduleName <> ".html") ]
146− [ HH.text moduleName ]
177+ [ HH.a [ HP.href (unwrap moduleName <> ".html") ]
178+ [ HH.text $ unwrap moduleName ]
147179 ]
148180
149− packageList :: Array (String /\ Set ModuleName)
150− packageList = Map.toUnfoldable moduleIndex
181+ packageList :: Array (PackageInfo /\ Set ModuleName)
182+ packageList = Map.toUnfoldable state.packageModules
151183
152184
153185-- | Decide whether to group modules by package in the sidebar, using localStorage.
@@ -155,8 +187,24 @@ loadGroupingModeFromLocalStorage :: Effect GroupingMode
155187loadGroupingModeFromLocalStorage = do
156188 window <- HTML.window
157189 localStorage <- Window.localStorage window
158− mbGroupModules <- Storage.getItem config.groupModulesItem localStorage
159− pure $ if isJust mbGroupModules then GroupByPackage else DontGroup
190+ mbDontGroupModules <- Storage.getItem Config.groupModulesItem localStorage
191+ pure $ if isJust mbDontGroupModules then DontGroup else GroupByPackage
192+
193+
194+-- | Extract current module name from page title element.
195+getCurrentModuleName :: Effect (Maybe ModuleName)
196+getCurrentModuleName = do
197+ win <- HTML.window
198+ docPN <- Document.toParentNode <$> HTMLDocument.toDocument <$> Window.document win
199+ mbPageTitleEl <- ParentNode.querySelector (wrap ".page-title__title") docPN
200+ map ModuleName <$> traverse (Node.textContent <<< Element.toNode) mbPageTitleEl
201+
202+
203+-- | Given a module name, get `PackageInfo` for a package this module name belongs to.
204+getCurrentPackage :: ModuleIndex -> Maybe ModuleName -> PackageInfo
205+getCurrentPackage { modulePackages } (Just moduleName) =
206+ fromMaybe UnknownPackage $ Map.lookup moduleName modulePackages
207+getCurrentPackage { modulePackages } Nothing = UnknownPackage
160208
161209
162210-- | Convert checkbox status to sidebar mode
@@ -167,4 +215,4 @@ isCheckedToGroupingMode = if _ then GroupByPackage else DontGroup
167215-- Some optics:
168216
169217_groupingMode :: forall a b rest. (a -> b) -> { groupingMode :: a | rest } -> { groupingMode :: b | rest }
170−_groupingMode = prop (SProxy :: SProxy "groupingMode")
218+_groupingMode = prop (Proxy :: Proxy "groupingMode")
src/Docs/Search/BrowserEngine.js+1−1
@@ -1,6 +1,6 @@
11/* global exports */
22
3−exports.loadIndex_ = function (partId) {
3+export function loadIndex_ (partId) {
44 return function (url) {
55 return function () {
66 return new Promise(function(resolve, reject) {
src/Docs/Search/BrowserEngine.purs+10−14
@@ -1,12 +1,13 @@
11-- | A search engine that is used in the browser.
22module Docs.Search.BrowserEngine where
33
4−import Docs.Search.Config (config)
4+import Docs.Search.Config as Config
55import Docs.Search.PackageIndex (queryPackageIndex)
66import Docs.Search.Engine (Engine, EngineState, Index)
77import Docs.Search.SearchResult (SearchResult)
88import Docs.Search.TypeIndex (TypeIndex)
99import Docs.Search.TypeIndex as TypeIndex
10+import Docs.Search.Types (PartId(..), URL)
1011import Docs.Search.ModuleIndex as ModuleIndex
1112
1213import Prelude
@@ -32,12 +33,9 @@ import Effect.Aff (Aff, try)
3233
3334
3435newtype PartialIndex
35− = PartialIndex (Map Int Index)
36+ = PartialIndex (Map PartId Index)
3637
3738derive instance newtypePartialIndex :: Newtype PartialIndex _
38−derive newtype instance semigroupPartialIndex :: Semigroup PartialIndex
39−derive newtype instance monoidPartialIndex :: Monoid PartialIndex
40−
4139
4240type BrowserEngineState = EngineState PartialIndex TypeIndex
4341
@@ -52,13 +50,11 @@ query
5250 -> Aff { index :: PartialIndex, results :: Array SearchResult }
5351query index@(PartialIndex indexMap) input = do
5452 let
55− path :: List Char
5653 path =
5754 List.fromFoldable $
5855 String.toCharArray $
5956 input
6057
61− partId :: Int
6258 partId = getPartId path
6359
6460 case Map.lookup partId indexMap of
@@ -68,7 +64,7 @@ query index@(PartialIndex indexMap) input = do
6864
6965
7066 eiPartJson <-
71− try $ toAffE $ loadIndex_ partId $ config.mkIndexPartLoadPath partId
67+ try $ toAffE $ loadIndex_ partId $ Config.mkIndexPartLoadPath partId
7268
7369 let
7470 mbNewTrie :: Maybe (Trie Char (List SearchResult))
@@ -119,16 +115,16 @@ browserSearchEngine =
119115
120116
121117-- | Find in which part of the index this path can be found.
122−getPartId :: List Char -> Int
118+getPartId :: List Char -> PartId
123119getPartId (a : b : _) =
124− (Char.toCharCode a + Char.toCharCode b) `mod` config.numberOfIndexParts
120+ PartId $ (Char.toCharCode a + Char.toCharCode b) `mod` Config.numberOfIndexParts
125121getPartId (a : _) =
126− Char.toCharCode a `mod` config.numberOfIndexParts
127−getPartId _ = 0
122+ PartId $ Char.toCharCode a `mod` Config.numberOfIndexParts
123+getPartId _ = PartId 0
128124
129125
130126-- | Load a part of the index by injecting a <script> tag into the DOM.
131127foreign import loadIndex_
132− :: Int
133− -> String
128+ :: PartId
129+ -> URL
134130 -> Effect (Promise Json)
src/Docs/Search/Config.purs+79−66
@@ -1,72 +1,85 @@
11module Docs.Search.Config where
22
3+import Docs.Search.Types (GlobalIdentifier, PackageName, PartId, URL, FilePath)
4+
35import Prelude
46
5−-- | Some magic constants.
6−config ::
7− { version :: String
8− , declIndexDirectory :: String
9− , mkIndexPartLoadPath :: Int -> String
10− , mkIndexPartPath :: Int -> String
11− , moduleIndexPath :: String
12− , moduleIndexLoadPath :: String
13− , groupModulesItem :: String
14− , packageInfoPath :: String
15− , packageInfoLoadPath :: String
16− , mkShapeScriptPath :: String -> String
17− , numberOfIndexParts :: Int
18− , outputDirectory :: String
19− , penalties :: { excessiveConstraint :: Int
20− , generalize :: Int
21− , instantiate :: Int
22− , match :: Int
23− , matchConstraint :: Int
24− , missingConstraint :: Int
25− , rowsMismatch :: Int
26− , typeVars :: Int
27− }
28− , requiredDirectories :: Array String
29− , resultsCount :: Int
30− , typeIndexDirectory :: String
7+import Data.Newtype (wrap)
8+
9+version :: String
10+version = "0.0.12"
11+
12+mkShapeScriptPath :: String -> String
13+mkShapeScriptPath shape = "./index/types/" <> shape <> ".js"
14+
15+-- | In how many parts the index should be splitted?
16+numberOfIndexParts :: Int
17+numberOfIndexParts = 50
18+
19+mkIndexPartPath :: PartId -> String
20+mkIndexPartPath partId = "html/index/declarations/" <> show partId <> ".js"
21+
22+mkIndexPartLoadPath :: PartId -> URL
23+mkIndexPartLoadPath partId = wrap $ "./index/declarations/" <> show partId <> ".js"
24+
25+moduleIndexPath :: FilePath
26+moduleIndexPath = wrap "generated-docs/html/index/modules.js"
27+
28+-- | Used to load mode index to the browser scope.
29+moduleIndexLoadPath :: String
30+moduleIndexLoadPath = "./index/modules.js"
31+
32+typeIndexDirectory :: FilePath
33+typeIndexDirectory = wrap "generated-docs/html/index/types"
34+
35+metaPath :: FilePath
36+metaPath = wrap "generated-docs/html/index/meta.js"
37+
38+metaLoadPath :: URL
39+metaLoadPath = wrap "./index/meta.js"
40+
41+metaItem :: GlobalIdentifier
42+metaItem = wrap "DocsSearchMeta"
43+
44+-- | localStorage key to save sidebar checkbox value to.
45+groupModulesItem :: String
46+groupModulesItem = "PureScriptDocsSearchGroupModules"
47+
48+packageInfoPath :: FilePath
49+packageInfoPath = wrap "generated-docs/html/index/packages.js"
50+
51+packageInfoItem :: GlobalIdentifier
52+packageInfoItem = wrap "DocsSearchPackageIndex"
53+
54+packageInfoLoadPath :: URL
55+packageInfoLoadPath = wrap "./index/packages.js"
56+
57+-- | How many results to show by default?
58+resultsCount :: Int
59+resultsCount = 25
60+
61+-- | Penalties used to determine how "far" a type query is from a given type.
62+-- See Docs.Search.TypeQuery
63+penalties ::
64+ { excessiveConstraint :: Int
65+ , generalize :: Int
66+ , instantiate :: Int
67+ , match :: Int
68+ , matchConstraint :: Int
69+ , missingConstraint :: Int
70+ , rowsMismatch :: Int
71+ , typeVars :: Int
3172 }
32−config =
33− { version: "0.0.8"
34− , outputDirectory: "output"
35− , requiredDirectories:
36− [ "generated-docs"
37− , "generated-docs/html"
38− , "output"
39− ]
40− -- ^ Directories required by IndexBuilder
41− , declIndexDirectory: "generated-docs/html/index/declarations"
42− , typeIndexDirectory: "generated-docs/html/index/types"
43− , mkShapeScriptPath:
44− \shape -> "./index/types/" <> shape <> ".js"
45− , numberOfIndexParts: 50
46− -- ^ In how many parts the index should be splitted?
47− , mkIndexPartPath:
48− \(partId :: Int) -> "html/index/declarations/" <> show partId <> ".js"
49− , mkIndexPartLoadPath:
50− \(partId :: Int) -> "./index/declarations/" <> show partId <> ".js"
51− , moduleIndexPath: "generated-docs/html/index/modules.js"
52− , moduleIndexLoadPath: "./index/modules.js"
53− -- ^ Used to load mode index to the browser scope.
54− , groupModulesItem: "PureScriptDocsSearchGroupModules"
55− -- ^ localStorage key to save sidebar checkbox value to.
56− , packageInfoPath: "generated-docs/html/index/packages.js"
57− , packageInfoLoadPath: "./index/packages.js"
58− -- ^ Used to load package index to the browser scope.
59− , resultsCount: 25
60− -- ^ How many results to show by default?
61− , penalties: { typeVars: 2
62− , match: 2
63− , matchConstraint: 1
64− , instantiate: 2
65− , generalize: 2
66− , rowsMismatch: 3
67− , missingConstraint: 1
68− , excessiveConstraint: 1
69− }
70− -- ^ Penalties used to determine how "far" a type query is from a given type.
71− -- See Docs.Search.TypeQuery
73+penalties =
74+ { typeVars: 2
75+ , match: 2
76+ , matchConstraint: 1
77+ , instantiate: 2
78+ , generalize: 2
79+ , rowsMismatch: 3
80+ , missingConstraint: 1
81+ , excessiveConstraint: 1
7282 }
83+
84+defaultPackageName :: PackageName
85+defaultPackageName = wrap "<local package>"
src/Docs/Search/Declarations.purs+77−48
@@ -1,20 +1,19 @@
11module Docs.Search.Declarations where
22
33import Docs.Search.DocsJson (ChildDeclType(..), ChildDeclaration(..), DeclType(..), Declaration(..), DocsJson(..), SourceSpan)
4−import Docs.Search.Score (Scores)
4+import Docs.Search.Score (Scores, getPackageScore, getPackageScoreForPackageName)
55import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
6−import Docs.Search.TypeDecoder (Constraint(..), QualifiedName(..), Type(..), Kind, joinForAlls)
7−import Docs.Search.Types (ModuleName, PackageName)
6+import Docs.Search.TypeDecoder (Constraint(..), QualifiedName(..), Type(..), joinForAlls)
7+import Docs.Search.Types (ModuleName(..), PackageName(..), PackageInfo(..), Identifier(..))
88
99import Prelude
10−
10+import Prim hiding (Type)
1111import Control.Alt ((<|>))
1212import Data.Array ((!!))
1313import Data.Array as Array
14−import Data.Foldable (foldr)
14+import Data.Foldable (foldl, foldr)
1515import Data.List (List, (:))
1616import Data.List as List
17−import Data.Map as Map
1817import Data.Maybe (Maybe(..), fromMaybe)
1918import Data.Newtype (class Newtype, unwrap, wrap)
2019import Data.Search.Trie (Trie, alter)
@@ -24,8 +23,7 @@ import Data.String.Common (toLower)
2423import Data.String.Pattern (Pattern(..))
2524
2625
27−newtype Declarations
28− = Declarations (Trie Char (List SearchResult))
26+newtype Declarations = Declarations (Trie Char (List SearchResult))
2927
3028derive instance newtypeDeclarations :: Newtype Declarations _
3129derive newtype instance semigroupDeclarations :: Semigroup Declarations
@@ -42,7 +40,7 @@ insertDocsJson
4240 -> Trie Char (List SearchResult)
4341 -> Trie Char (List SearchResult)
4442insertDocsJson scores (DocsJson { name, declarations }) trie
45− = foldr (insertDeclaration scores name) trie declarations
43+ = foldr (insertDeclaration scores $ ModuleName name) trie declarations
4644
4745
4846insertDeclaration
@@ -63,13 +61,13 @@ insertSearchResult
6361 -> Trie Char (List SearchResult)
6462insertSearchResult { path, result } trie =
6563 let path' = List.fromFoldable $ toCharArray $ toLower path in
66− alter path' (Just <<< updateResults) trie
67− where
68− updateResults mbOldResults
69− | Just oldResults <- mbOldResults =
70− result : oldResults
71− | otherwise =
72− List.singleton result
64+ alter path' (Just <<< updateResults) trie
65+ where
66+ updateResults mbOldResults
67+ | Just oldResults <- mbOldResults =
68+ result : oldResults
69+ | otherwise =
70+ List.singleton result
7371
7472
7573-- | For each declaration, extract its own `SearchResult` and `SearchResult`s
@@ -82,19 +80,17 @@ resultsForDeclaration
8280 , result :: SearchResult
8381 }
8482resultsForDeclaration scores moduleName indexEntry@(Declaration entry) =
85− let { info, title, sourceSpan, comments, children } = entry
86− { name, declLevel } = getLevelAndName info.declType title
87− packageName = extractPackageName moduleName sourceSpan
88− in case mkInfo declLevel indexEntry of
89− Nothing -> mempty
90− Just info' ->
91− let result = SearchResult { name: title
83+ case mkInfo declLevel indexEntry of
84+ Nothing -> mempty
85+ Just info' ->
86+ let result = SearchResult { name: Identifier title
9287 , comments
9388 , hashAnchor: declLevelToHashAnchor declLevel
9489 , moduleName
9590 , sourceSpan
96− , packageName
97− , score: fromMaybe 0 $ Map.lookup packageName scores
91+ , packageInfo
92+ , score:
93+ fromMaybe zero $ getPackageScoreForPackageName scores <$> mbPackageName
9894 , info: info'
9995 }
10096 in
@@ -104,8 +100,16 @@ resultsForDeclaration scores moduleName indexEntry@(Declaration entry) =
104100 }
105101 ) <>
106102 ( List.fromFoldable children >>=
107− resultsForChildDeclaration scores packageName moduleName result
103+ resultsForChildDeclaration scores packageInfo moduleName result
108104 )
105+ where
106+ { info, title, sourceSpan, comments, children } = entry
107+ { name, declLevel } = getLevelAndName info.declType title
108+ packageInfo = extractPackageName moduleName sourceSpan
109+ mbPackageName =
110+ case packageInfo of
111+ Package packageName -> Just packageName
112+ _ -> Nothing
109113
110114
111115mkInfo :: DeclLevel -> Declaration -> Maybe ResultInfo
@@ -188,35 +192,34 @@ getLevelAndName DeclExternKind name = { name, declLevel: KindLevel }
188192-- | Extract package name from `sourceSpan.name`, which contains path to
189193-- | the source file. If `ModuleName` string starts with `Prim.`, it's a
190194-- | built-in (guaranteed by the compiler).
191−extractPackageName :: ModuleName -> Maybe SourceSpan -> PackageName
192−extractPackageName moduleName _
193− | String.split (Pattern ".") moduleName !! 0 == Just "Prim" = "<builtin>"
194−extractPackageName _ Nothing = "<unknown>"
195+extractPackageName :: ModuleName -> Maybe SourceSpan -> PackageInfo
196+extractPackageName (ModuleName moduleName) _
197+ | String.split (Pattern ".") moduleName !! 0 == Just "Prim" = Builtin
198+extractPackageName _ Nothing = UnknownPackage
195199extractPackageName _ (Just { name }) =
196− let dirs = String.split (Pattern "/") name
197− in
198− fromMaybe "<local package>" do
199− topLevelDir <- dirs !! 0
200− if topLevelDir == ".spago"
201− then dirs !! 1
202− else do
203− bowerDirIx <- Array.findIndex (_ == "bower_components") dirs
204− dirs !! (bowerDirIx + 1)
200+ fromMaybe LocalPackage do
201+ topLevelDir <- dirs !! 0
202+ if topLevelDir == ".spago"
203+ then Package <<< PackageName <$> dirs !! 1
204+ else do
205+ bowerDirIx <- Array.findIndex (_ == "bower_components") dirs
206+ Package <<< PackageName <$> dirs !! (bowerDirIx + 1)
207+ where dirs = String.split (Pattern "/") name
205208
206209
207210-- | Extract `SearchResults` from a `ChildDeclaration`.
208211resultsForChildDeclaration
209212 :: Scores
210− -> PackageName
213+ -> PackageInfo
211214 -> ModuleName
212215 -> SearchResult
213216 -> ChildDeclaration
214217 -> List { path :: String, result :: SearchResult }
215−resultsForChildDeclaration scores packageName moduleName parentResult
218+resultsForChildDeclaration scores packageInfo moduleName parentResult
216219 child@(ChildDeclaration { title, info, comments, mbSourceSpan })
217220 | Just resultInfo <- mkChildInfo parentResult child =
218221 { path: title
219− , result: SearchResult { name: title
222+ , result: SearchResult { name: Identifier title
220223 , comments
221224 -- `ChildDeclaration`s are always either data
222225 -- constructors, type class members or instances.
@@ -225,8 +228,8 @@ resultsForChildDeclaration scores packageName moduleName parentResult
225228 , hashAnchor: "v"
226229 , moduleName
227230 , sourceSpan: mbSourceSpan
228− , packageName
229− , score: fromMaybe 0 $ Map.lookup packageName scores
231+ , packageInfo
232+ , score: getPackageScore scores packageInfo
230233 , info: resultInfo
231234 }
232235 } # List.singleton
@@ -241,8 +244,33 @@ mkChildInfo
241244 (SearchResult { info: parentInfo, moduleName, name: resultName })
242245 (ChildDeclaration { info } )
243246
244− | ChildDeclDataConstructor <- info.declType =
245− info.arguments <#> \arguments -> DataConstructorResult { arguments }
247+ | ChildDeclDataConstructor <- info.declType
248+ , DataResult { dataDeclType, typeArguments } <- parentInfo =
249+ let
250+ parentTypeCtor :: Type
251+ parentTypeCtor = TypeConstructor
252+ $ QualifiedName { moduleNameParts:
253+ String.split (wrap ".") (unwrap moduleName)
254+ , name: resultName }
255+
256+ parentTypeArgs :: Array Type
257+ parentTypeArgs = typeArguments <#> unwrap >>> \{ name } -> TypeVar name
258+
259+ parentType :: Type
260+ parentType = foldl TypeApp parentTypeCtor parentTypeArgs
261+
262+ typeArrow :: Type -> Type
263+ typeArrow =
264+ TypeApp (TypeConstructor (QualifiedName { moduleNameParts: [ "Prim" ]
265+ , name: Identifier "Function" }))
266+
267+ makeType :: Array Type -> Type
268+ makeType = foldr (\a b -> TypeApp (typeArrow a) b) parentType
269+ in
270+ info.arguments <#> \arguments ->
271+ DataConstructorResult { dataDeclType
272+ , "type": makeType arguments
273+ }
246274
247275 | ChildDeclTypeClassMember <- info.declType
248276 , TypeClassResult { arguments } <- parentInfo =
@@ -261,13 +289,14 @@ mkChildInfo
261289
262290 -- Then we construct a qualified name of the type class.
263291 constraintClass =
264− QualifiedName { moduleName: String.split (wrap ".") moduleName
292+ QualifiedName { moduleNameParts:
293+ String.split (wrap ".") $ unwrap moduleName
265294 , name: resultName }
266295
267296 -- We concatenate two lists:
268297 -- * a list of type parameters of the type class, and
269298 -- * a list of quantified variables of the unconstrained type
270− allArguments :: Array { name :: String, mbKind :: Maybe Kind }
299+ allArguments :: Array { name :: String, mbKind :: Maybe Type }
271300 allArguments =
272301 (arguments <#> unwrap) <> List.toUnfoldable binders
273302
src/Docs/Search/DocsJson.purs+15−10
@@ -2,15 +2,16 @@
22module Docs.Search.DocsJson where
33
44import Prelude
5−
6−import Docs.Search.TypeDecoder (Constraint, FunDeps, Kind, Type, TypeArgument)
5+import Prim hiding (Type, Constraint)
6+import Docs.Search.TypeDecoder (Constraint, FunDeps, Type, TypeArgument)
77
88import Data.Argonaut.Core (fromString, stringify, toString)
99import Data.Argonaut.Decode (class DecodeJson, decodeJson, (.:), (.:?))
10+import Data.Argonaut.Decode.Error (JsonDecodeError(..))
1011import Data.Argonaut.Encode (class EncodeJson, encodeJson)
1112import Data.Either (Either(..))
1213import Data.Generic.Rep (class Generic)
13−import Data.Generic.Rep.Show (genericShow)
14+import Data.Show.Generic (genericShow)
1415import Data.Maybe (Maybe(..))
1516import Data.Newtype (class Newtype, unwrap)
1617
@@ -43,7 +44,7 @@ newtype Declaration
4344 , comments :: Maybe String
4445 , info :: { declType :: DeclType
4546 , dataDeclType :: Maybe DataDeclType
46− , kind :: Maybe Kind
47+ , kind :: Maybe Type
4748 , typeArguments :: Maybe (Array TypeArgument)
4849 , type :: Maybe Type
4950 , superclasses :: Maybe (Array Constraint)
@@ -151,7 +152,7 @@ instance encodeJsonDeclType :: EncodeJson DeclType where
151152instance decodeJsonDeclType :: DecodeJson DeclType where
152153 decodeJson json =
153154 case toString json of
154− Nothing -> Left $ "Couldn't decode DeclType: " <> stringify json
155+ Nothing -> errorWith $ "Couldn't decode DeclType: " <> stringify json
155156 Just string ->
156157 case string of
157158 "value" -> Right DeclValue
@@ -161,7 +162,7 @@ instance decodeJsonDeclType :: DecodeJson DeclType where
161162 "typeClass" -> Right DeclTypeClass
162163 "alias" -> Right DeclAlias
163164 "kind" -> Right DeclExternKind
164− _ -> Left $ "Couldn't decode DeclType: " <> string
165+ _ -> errorWith $ "Couldn't decode DeclType: " <> string
165166
166167
167168data ChildDeclType
@@ -184,13 +185,13 @@ instance encodeJsonChildDeclType :: EncodeJson ChildDeclType where
184185instance decodeJsonChildDeclType :: DecodeJson ChildDeclType where
185186 decodeJson json =
186187 case toString json of
187− Nothing -> Left $ "Couldn't decode ChildDeclType: " <> stringify json
188+ Nothing -> errorWith $ "Couldn't decode ChildDeclType: " <> stringify json
188189 Just tag ->
189190 case tag of
190191 "instance" -> Right ChildDeclInstance
191192 "dataConstructor" -> Right ChildDeclDataConstructor
192193 "typeClassMember" -> Right ChildDeclTypeClassMember
193− _ -> Left $ "Couldn't decode ChildDeclType: " <> tag
194+ _ -> errorWith $ "Couldn't decode ChildDeclType: " <> tag
194195
195196
196197data DataDeclType
@@ -215,5 +216,9 @@ instance decodeJsonDataDeclType :: DecodeJson DataDeclType where
215216 case tag of
216217 "newtype" -> Right NewtypeDataDecl
217218 "data" -> Right DataDataDecl
218− _ -> Left $ "Couldn't decode DataDeclType: " <> tag
219− Nothing -> Left $ "Couldn't decode DataDeclType: " <> stringify json
219+ _ -> errorWith $ "Couldn't decode DataDeclType: " <> tag
220+ Nothing -> errorWith $ "Couldn't decode DataDeclType: " <> stringify json
221+
222+
223+errorWith :: forall a. String -> Either JsonDecodeError a
224+errorWith = Left <<< TypeMismatch
src/Docs/Search/Engine.purs+27−10
@@ -5,7 +5,7 @@ import Docs.Search.PackageIndex (PackageIndex, PackageResult)
55import Docs.Search.Score (Scores)
66import Docs.Search.SearchResult (SearchResult, typeOfResult)
77import Docs.Search.TypeQuery (TypeQuery(..), parseTypeQuery, penalty)
8−import Docs.Search.Types (PackageName, ModuleName)
8+import Docs.Search.Types (PackageInfo(..), ModuleName(..), PackageName(..), PackageScore)
99
1010import Prelude
1111
@@ -66,27 +66,34 @@ data Result
6666 | MdlResult ModuleResult
6767
6868
69−getResultScore :: Result -> Int
69+getResultScore :: Result -> PackageScore
7070getResultScore (DeclResult r) = (unwrap r).score
7171getResultScore (TypeResult r) = (unwrap r).score
7272getResultScore (PackResult r) = r.score
7373getResultScore (MdlResult r) = r.score
7474
7575
76−getResultPackageName :: Result -> PackageName
77−getResultPackageName (DeclResult r) = (unwrap r).packageName
78−getResultPackageName (TypeResult r) = (unwrap r).packageName
79−getResultPackageName (PackResult r) = r.name
80−getResultPackageName (MdlResult r) = r.package
76+getResultPackageInfo :: Result -> PackageInfo
77+getResultPackageInfo (DeclResult r) = (unwrap r).packageInfo
78+getResultPackageInfo (TypeResult r) = (unwrap r).packageInfo
79+getResultPackageInfo (PackResult r) = Package r.name
80+getResultPackageInfo (MdlResult r) = r.package
8181
8282
8383getResultModuleName :: Result -> ModuleName
8484getResultModuleName (DeclResult r) = (unwrap r).moduleName
8585getResultModuleName (TypeResult r) = (unwrap r).moduleName
86−getResultModuleName (PackResult r) = ""
86+getResultModuleName (PackResult r) = ModuleName ""
8787getResultModuleName (MdlResult r) = r.name
8888
8989
90+getResultName :: Result -> String
91+getResultName (DeclResult r) = unwrap (unwrap r).name
92+getResultName (TypeResult r) = unwrap (unwrap r).name
93+getResultName (PackResult r) = unwrap r.name
94+getResultName (MdlResult r) = unwrap r.name
95+
96+
9097sortByPopularity
9198 :: forall index typeIndex
9299 . EngineState index typeIndex
@@ -95,8 +102,11 @@ sortByPopularity
95102sortByPopularity { packageIndex } =
96103 Array.sortBy (
97104 compare `on` (getResultScore >>> negate) <>
98− compare `on` getResultPackageName <>
99− compare `on` getResultModuleName
105+ compare `on` getResultPackageInfo <>
106+ compare `on` getResultModuleName <>
107+ -- Identifier name comes last: we want to make sure no `Result`s are
108+ -- equal, to avoid having unstable ordering.
109+ compare `on` getResultName
100110 )
101111
102112
@@ -148,3 +158,10 @@ sortByDistance
148158 -> Array SearchResult
149159sortByDistance typeQuery =
150160 Array.sortWith (map (penalty typeQuery) <<< typeOfResult)
161+
162+
163+packageInfoToString :: PackageName -> PackageInfo -> String
164+packageInfoToString _ (Package (PackageName p)) = p
165+packageInfoToString _ Builtin = "<builtin>"
166+packageInfoToString localPackageName LocalPackage = unwrap localPackageName
167+packageInfoToString _ UnknownPackage = "<unknown package>"
src/Docs/Search/IndexBuilder.js+4−5
@@ -1,14 +1,13 @@
11/* global __dirname require exports */
22
3−var path = require('path');
4−var glob = require('glob');
3+import globMain from "glob";
54
6−exports.getDirname = function () {
5+export function getDirname () {
76 return __dirname;
87};
98
10−exports.glob = function (pattern) {
9+export function glob (pattern) {
1110 return function () {
12− return glob.sync(pattern);
11+ return globMain.sync(pattern);
1312 };
1413};
src/Docs/Search/IndexBuilder.purs+70−25
@@ -1,21 +1,27 @@
11module Docs.Search.IndexBuilder where
22
33import Docs.Search.BrowserEngine (getPartId)
4−import Docs.Search.Config (config)
4+import Docs.Search.Config as Config
55import Docs.Search.Declarations (Declarations(..), mkDeclarations)
66import Docs.Search.DocsJson (DocsJson)
77import Docs.Search.Extra ((>#>))
8+import Docs.Search.Meta (Meta)
89import Docs.Search.ModuleIndex (PackedModuleIndex, mkPackedModuleIndex)
10+import Docs.Search.ModuleParser (parseModuleName)
911import Docs.Search.PackageIndex (PackageInfo, mkPackageInfo)
1012import Docs.Search.Score (mkScores)
1113import Docs.Search.SearchResult (SearchResult)
1214import Docs.Search.TypeIndex (TypeIndex, mkTypeIndex)
15+import Docs.Search.Types (ModuleName, PackageName, PartId)
1316
1417import Prelude
18+
1519import Data.Argonaut.Core (stringify)
1620import Data.Argonaut.Decode (decodeJson)
21+import Data.Argonaut.Decode.Error (printJsonDecodeError)
1722import Data.Argonaut.Encode (encodeJson)
1823import Data.Argonaut.Parser (jsonParser)
24+import Data.Array (concat)
1925import Data.Array as Array
2026import Data.Either (Either(..), either)
2127import Data.Foldable (sum)
@@ -25,6 +31,7 @@ import Data.Map (Map)
2531import Data.Map as Map
2632import Data.Maybe (Maybe(..), fromMaybe)
2733import Data.Newtype (unwrap)
34+import Data.Profunctor.Choice (left)
2835import Data.Search.Trie as Trie
2936import Data.Set as Set
3037import Data.String.CodePoints (contains) as String
@@ -33,13 +40,15 @@ import Data.String.Common (replace) as String
3340import Data.String.Pattern (Pattern(..), Replacement(..))
3441import Data.Traversable (for, for_)
3542import Data.Tuple (Tuple(..), fst)
43+import Data.Tuple.Nested ((/\))
3644import Effect (Effect)
3745import Effect.Aff (Aff, launchAff_, parallel, sequential)
3846import Effect.Class (liftEffect)
3947import Effect.Console (log)
4048import Node.Encoding (Encoding(UTF8))
41−import Node.FS.Aff (exists, mkdir, readFile, readTextFile, readdir, stat, writeFile, writeTextFile)
49+import Node.FS.Aff (mkdir, readFile, readTextFile, readdir, stat, writeFile, writeTextFile)
4250import Node.FS.Stats (isDirectory, isFile)
51+import Node.FS.Sync (exists)
4352import Node.Process as Process
4453import Web.Bower.PackageMeta (PackageMeta(..))
4554
@@ -49,6 +58,8 @@ type Config =
4958 , bowerFiles :: Array String
5059 , generatedDocs :: String
5160 , noPatch :: Boolean
61+ , packageName :: PackageName
62+ , sourceFiles :: Array String
5263 }
5364
5465
@@ -64,39 +75,44 @@ run' cfg = do
6475 liftEffect do
6576 log "Building the search index..."
6677
67− docsJsons <- decodeDocsJsons cfg
68− packageMetas <- decodeBowerJsons cfg
78+ docsJsons /\ moduleNames /\ packageMetas <- sequential $
79+ (\d h m -> d /\ h /\ m)
80+ <$> parallel (decodeDocsJsons cfg)
81+ <*> parallel (parseModuleHeaders cfg.sourceFiles)
82+ <*> parallel (decodeBowerJsons cfg)
83+
84+ let countOfPackages = Array.length packageMetas
85+ countOfModules = Array.length docsJsons
6986
7087 liftEffect do
7188 log $
7289 "Indexing " <>
73− show (Array.length docsJsons) <>
90+ show countOfModules <>
7491 " modules from " <>
75− show (Array.length packageMetas) <>
92+ show countOfPackages <>
7693 " packages..."
7794
7895 let scores = mkScores packageMetas
7996 index = mkDeclarations scores docsJsons
8097 typeIndex = mkTypeIndex scores docsJsons
8198 packageInfo = mkPackageInfo scores packageMetas
82− moduleIndex = mkPackedModuleIndex index
99+ moduleIndex = mkPackedModuleIndex index moduleNames
100+ meta = { localPackageName: cfg.packageName }
83101
84102 createDirectories cfg
85103
86104 void $ sequential do
87105 ignore <$> parallel (writeIndex cfg index)
88− <*> parallel (writeTypeIndex cfg typeIndex)
106+ <*> parallel (writeTypeIndex typeIndex)
89107 <*> parallel (writePackageInfo packageInfo)
90108 <*> parallel (writeModuleIndex moduleIndex)
91− <*> parallel (if cfg.noPatch
92− then pure unit
93− else patchDocs cfg)
109+ <*> parallel (writeMeta meta)
110+ <*> parallel (when (not cfg.noPatch) $ patchDocs cfg)
94111 <*> parallel (copyAppFile cfg)
95112
96113 let countOfDefinitions = Trie.size $ unwrap index
97114 countOfTypeDefinitions =
98115 sum $ fromMaybe 0 <$> map Array.length <$> Map.values (unwrap typeIndex)
99− countOfPackages = Array.length packageMetas
100116
101117 liftEffect do
102118 log $
@@ -146,7 +162,7 @@ decodeDocsJsons cfg@{ docsFiles } = do
146162 if doesExist then do
147163
148164 contents <- readTextFile UTF8 jsonFile
149− let eiResult = jsonParser contents >>= decodeJson
165+ let eiResult = jsonParser contents >>= left printJsonDecodeError <<< decodeJson
150166
151167 case eiResult of
152168 Left error -> do
@@ -167,6 +183,28 @@ decodeDocsJsons cfg@{ docsFiles } = do
167183
168184 pure docsJsons
169185
186+-- | This function accepts an array of globs pointing to project sources
187+-- | and returns a list of module names extracted from these files.
188+-- | Unfortunately, we can't get all module names from `docs.json`s, because
189+-- | reexport-only modules do not have a single declaration in them, so we can't
190+-- | count them normally in `mkPackedModuleIndex.extract`, where we only look at
191+-- | exported declarations.
192+parseModuleHeaders :: Array String -> Aff (Array ModuleName)
193+parseModuleHeaders globs = do
194+ files <- getPathsByGlobs globs
195+
196+ -- we are not checking if the globs match at least one file, because
197+ -- we want to support scenarios where there is no "current project"
198+
199+ concat <$> for files \filePath -> do
200+ fileContents <- readTextFile UTF8 filePath
201+ case parseModuleName fileContents of
202+ Nothing -> do
203+ liftEffect $ log $
204+ "Module header decoding failed for " <> filePath <>
205+ ", unable to extract module name"
206+ pure []
207+ Just res -> pure [res]
170208
171209decodeBowerJsons
172210 :: forall rest
@@ -187,7 +225,7 @@ decodeBowerJsons { bowerFiles } = do
187225 join <$> withExisting jsonFileName
188226 \contents ->
189227 either (logError jsonFileName) pure
190− (jsonParser contents >>= decodeJson)
228+ (jsonParser contents >>= left printJsonDecodeError <<< decodeJson)
191229
192230 where
193231 compareNames
@@ -201,10 +239,10 @@ decodeBowerJsons { bowerFiles } = do
201239
202240
203241-- | Write type index parts to files.
204−writeTypeIndex :: Config -> TypeIndex -> Aff Unit
205−writeTypeIndex { generatedDocs } typeIndex =
242+writeTypeIndex :: TypeIndex -> Aff Unit
243+writeTypeIndex typeIndex =
206244 for_ entries \(Tuple typeShape results) -> do
207− writeTextFile UTF8 (config.typeIndexDirectory <> "/" <> typeShape <> ".js")
245+ writeTextFile UTF8 (unwrap Config.typeIndexDirectory <> "/" <> typeShape <> ".js")
208246 (mkHeader typeShape <> stringify (encodeJson results))
209247 where
210248 mkHeader typeShape =
@@ -217,7 +255,7 @@ writeTypeIndex { generatedDocs } typeIndex =
217255writePackageInfo :: PackageInfo -> Aff Unit
218256writePackageInfo packageInfo = do
219257
220− writeTextFile UTF8 config.packageInfoPath $
258+ writeTextFile UTF8 (unwrap Config.packageInfoPath) $
221259 header <> stringify (encodeJson packageInfo)
222260
223261 where
@@ -226,15 +264,22 @@ writePackageInfo packageInfo = do
226264
227265writeModuleIndex :: PackedModuleIndex -> Aff Unit
228266writeModuleIndex moduleIndex = do
229− writeTextFile UTF8 config.moduleIndexPath $
267+ writeTextFile UTF8 (unwrap Config.moduleIndexPath) $
230268 header <> stringify (encodeJson moduleIndex)
231269 where
232270 header = "window.DocsSearchModuleIndex = "
233271
272+writeMeta :: Meta -> Aff Unit
273+writeMeta meta = do
274+ writeTextFile UTF8 (unwrap Config.metaPath) $
275+ header <> stringify (encodeJson meta)
276+ where
277+ header = "window." <> unwrap Config.metaItem <> " = "
278+
234279-- | Get a mapping from index parts to index contents.
235−getIndex :: Declarations -> Map Int (Array (Tuple String (Array SearchResult)))
280+getIndex :: Declarations -> Map PartId (Array (Tuple String (Array SearchResult)))
236281getIndex (Declarations trie) =
237− Array.foldr insert mempty parts
282+ Array.foldr insert Map.empty parts
238283 where
239284 insert part = Map.insertWith append (getPartId part.prefix) part.results
240285
@@ -249,7 +294,7 @@ getIndex (Declarations trie) =
249294 Trie.query prefix trie
250295 else
251296 -- Entries with path lengths > 1 have been added already.
252− List.filter (\(Tuple path value) -> List.length path == 1) (
297+ List.filter (\(Tuple path _value) -> List.length path == 1) (
253298 Trie.query prefix trie
254299 )
255300 in
@@ -273,7 +318,7 @@ writeIndex { generatedDocs } = getIndex >>> \resultsMap -> do
273318 "// This file was generated by purescript-docs-search.\n" <>
274319 "window.DocsSearchIndex[\"" <> show indexPartId <> "\"] = "
275320
276− writeTextFile UTF8 (generatedDocs <> config.mkIndexPartPath indexPartId) $
321+ writeTextFile UTF8 (generatedDocs <> Config.mkIndexPartPath indexPartId) $
277322 header <> stringify (encodeJson results)
278323
279324
@@ -354,7 +399,7 @@ copyAppFile { generatedDocs } = do
354399
355400directoryExists :: String -> Aff Boolean
356401directoryExists path = do
357− doesExist <- exists path
402+ doesExist <- liftEffect $ exists path
358403 case doesExist of
359404 false -> pure false
360405 true -> isDirectory <$> stat path
@@ -362,7 +407,7 @@ directoryExists path = do
362407
363408fileExists :: String -> Aff Boolean
364409fileExists path = do
365− doesExist <- exists path
410+ doesExist <- liftEffect $ exists path
366411 case doesExist of
367412 false -> pure false
368413 true -> isFile <$> stat path
src/Docs/Search/Interactive.purs+103−61
@@ -1,21 +1,12 @@
11-- | Definitions for the "search REPL".
22module Docs.Search.Interactive where
33
4−import Prelude
5−
6−import Data.Array as Array
7−import Data.Identity (Identity(..))
8−import Data.Maybe (fromMaybe)
9−import Data.Newtype (un, unwrap, wrap)
10−import Data.Search.Trie as Trie
11−import Data.String (length) as String
12−import Data.String.Common (split, trim) as String
13−import Data.Tuple (fst)
144import Docs.Search.Declarations (Declarations, mkDeclarations)
155import Docs.Search.DocsJson (DataDeclType(..))
16−import Docs.Search.Engine (mkEngineState, Result(..))
6+import Docs.Search.Engine (mkEngineState, packageInfoToString, Result(..))
177import Docs.Search.Engine as Engine
18−import Docs.Search.Extra (listToString, stringToList, (>#>))
8+import Docs.Search.Extra (stringToList, (>#>))
9+import Docs.Search.IndexBuilder (parseModuleHeaders)
1910import Docs.Search.IndexBuilder as IndexBuilder
2011import Docs.Search.ModuleIndex (ModuleResult, mkPackedModuleIndex, unpackModuleIndex)
2112import Docs.Search.NodeEngine (nodeEngine)
@@ -23,19 +14,36 @@ import Docs.Search.PackageIndex (PackageResult, mkPackageIndex, mkPackageInfo)
2314import Docs.Search.Score (mkScores)
2415import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
2516import Docs.Search.Terminal (bold, cyan, green, yellow)
26−import Docs.Search.TypeDecoder (Constraint, FunDeps, Kind, QualifiedName, Type, TypeArgument)
17+import Docs.Search.TypeDecoder (Constraint, FunDeps, QualifiedName, Type, TypeArgument)
2718import Docs.Search.TypeIndex (resultsWithTypes)
28−import Docs.Search.TypePrinter (keyword, showConstraint, showFunDeps, showKind, showType, showTypeArgument, space, syntax)
19+import Docs.Search.TypePrinter (keyword, showConstraint, showFunDeps, showType, showTypeArgument, space, syntax)
20+import Docs.Search.Types (ModuleName, PackageName, PackageInfo, Identifier)
21+
22+import Prelude
23+
24+import Control.Parallel (parallel, sequential)
25+import Data.Array as Array
26+import Data.Identity (Identity(..))
27+import Data.List as List
28+import Data.Maybe (fromMaybe)
29+import Data.Newtype (un, unwrap, wrap)
30+import Data.Search.Trie as Trie
31+import Data.String (length) as String
32+import Data.String.Common (split, toLower, trim) as String
33+import Data.Tuple.Nested ((/\))
2934import Effect (Effect)
3035import Effect.Aff (launchAff_)
3136import Effect.Class (liftEffect)
3237import Effect.Console (log, clear) as Console
3338import Node.ReadLine (createConsoleInterface, question)
39+import Prim hiding (Type, Constraint)
3440
3541
3642type Config =
3743 { docsFiles :: Array String
3844 , bowerFiles :: Array String
45+ , packageName :: PackageName
46+ , sourceFiles :: Array String
3947 }
4048
4149
@@ -45,14 +53,17 @@ run cfg = launchAff_ $ do
4553 liftEffect do
4654 Console.log "Loading search index..."
4755
48− docsJsons <- IndexBuilder.decodeDocsJsons cfg
49− packageMetas <- IndexBuilder.decodeBowerJsons cfg
56+ docsJsons /\ moduleNames /\ packageMetas <- sequential $
57+ (\d h m -> d /\ h /\ m)
58+ <$> parallel (IndexBuilder.decodeDocsJsons cfg)
59+ <*> parallel (parseModuleHeaders cfg.sourceFiles)
60+ <*> parallel (IndexBuilder.decodeBowerJsons cfg)
5061
5162 let scores = mkScores packageMetas
5263 index = mkDeclarations scores docsJsons
5364 typeIndex = docsJsons >>= resultsWithTypes scores
5465 packageIndex = mkPackageIndex $ mkPackageInfo scores packageMetas
55− moduleIndex = unpackModuleIndex $ mkPackedModuleIndex index
66+ moduleIndex = unpackModuleIndex $ mkPackedModuleIndex index moduleNames
5667 engineState = mkEngineState (unwrap index) typeIndex packageIndex moduleIndex scores
5768
5869 let countOfDefinitions = Trie.size $ unwrap index
@@ -86,7 +97,7 @@ run cfg = launchAff_ $ do
8697 Console.log $
8798 if total > 0 then do
8899 Array.intercalate "\n\n\n" $
89− showResult <$> Array.reverse results
100+ showResult cfg <$> Array.reverse results
90101 else
91102 "Your search for " <> bold input <> " did not yield any results."
92103
@@ -103,60 +114,67 @@ mkCompleter
103114 -> Effect { completions :: Array String
104115 , matched :: String }
105116mkCompleter index input = do
106− let path = stringToList input
107− let paths =
117+ let path = stringToList $ String.toLower input
118+ paths =
108119 Array.fromFoldable $
109− listToString <$>
110− (fst <$> Trie.query path (unwrap index))
120+ (\result -> unwrap (unwrap result).name) <$>
121+ List.concat (Trie.queryValues path (unwrap index))
111122
112− pure { completions: paths
113− , matched: input }
123+ pure { completions: paths, matched: input }
114124
115125
116−showResult :: Result -> String
117−showResult = case _ of
118− DeclResult r -> showSearchResult r
119− TypeResult r -> showSearchResult r
126+showResult :: Config -> Result -> String
127+showResult cfg = case _ of
128+ DeclResult r -> showSearchResult cfg r
129+ TypeResult r -> showSearchResult cfg r
120130 PackResult r -> showPackageResult r
121131 MdlResult r -> showModuleResult r
122132
123133
124−showSearchResult :: SearchResult -> String
125−showSearchResult (SearchResult result@{ name, comments, moduleName, packageName }) =
134+showSearchResult :: Config -> SearchResult -> String
135+showSearchResult cfg (SearchResult result@{ name, comments, moduleName, packageInfo }) =
126136 showSignature result <> "\n" <>
127137
128138 (fromMaybe "\n" $
129139 comments <#> \comment ->
130140 "\n" <> leftShift 3 (String.trim comment) <> "\n\n") <>
131141
132− bold (cyan (rightPad 40 packageName)) <> space <> bold (green moduleName)
142+ bold (
143+ cyan (rightPad 40 $ packageInfoToString cfg.packageName packageInfo)
144+ ) <>
145+ space <>
146+ showModuleName moduleName
133147
134148
135149showPackageResult :: PackageResult -> String
136150showPackageResult { name, description } =
137− bold (cyan "package") <> " " <> bold (yellow name) <>
151+ bold (cyan "package") <> " " <> bold (yellow $ unwrap name) <>
138152
139153 (description >#> \text -> "\n\n" <> leftShift 3 text <> "\n")
140154
141155
142156showModuleResult :: ModuleResult -> String
143157showModuleResult { name, package } =
144− bold (cyan "module") <> " " <> bold (green name)
158+ bold (cyan "module") <> " " <> showModuleName name
145159
146160
147−showSignature ::
148− forall rest.
149− { name :: String
150− , moduleName :: String
151− , packageName :: String
152− , info :: ResultInfo
153− | rest
154− }
161+showModuleName :: ModuleName -> String
162+showModuleName = bold <<< green <<< unwrap
163+
164+
165+showSignature
166+ :: forall rest
167+ . { name :: Identifier
168+ , moduleName :: ModuleName
169+ , packageInfo :: PackageInfo
170+ , info :: ResultInfo
171+ | rest
172+ }
155173 -> String
156174showSignature result@{ name, info } =
157175 case info of
158176 ValueResult { type: ty } ->
159− yellow name <> syntax " :: " <> showType ty
177+ yellow (unwrap name) <> syntax " :: " <> showType ty
160178
161179 TypeClassResult info' ->
162180 showTypeClassSignature info' result
@@ -174,9 +192,12 @@ showSignature result@{ name, info } =
174192 showExternDataSignature info' result
175193
176194 ValueAliasResult ->
177− yellow ("(" <> name <> ")")
195+ yellow ("(" <> unwrap name <> ")")
196+
197+ DataConstructorResult info' ->
198+ showDataConstructorSignature info' result
178199
179− _ -> yellow name
200+ _ -> yellow $ unwrap name
180201
181202
182203showTypeClassSignature
@@ -185,7 +206,7 @@ showTypeClassSignature
185206 , arguments :: Array TypeArgument
186207 , superclasses :: Array Constraint
187208 }
188− -> { name :: String, moduleName :: String | rest }
209+ -> { name :: Identifier, moduleName :: ModuleName | rest }
189210 -> String
190211showTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName } =
191212
@@ -199,12 +220,11 @@ showTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName }
199220 superclasses <#> showConstraint
200221 )
201222 ) <>
202− syntax ")" <>
203− space <>
223+ syntax ") " <>
204224 syntax "<="
205225 ) <>
206226 space <>
207− yellow name <>
227+ yellow (unwrap name) <>
208228 space <> (
209229 Array.intercalate space $
210230 arguments <#> showTypeArgument
@@ -215,14 +235,14 @@ showTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName }
215235
216236showTypeClassMemberSignature
217237 :: forall rest
218− . { type :: Type
238+ . { "type" :: Type
219239 , typeClass :: QualifiedName
220240 , typeClassArguments :: Array TypeArgument
221241 }
222− -> { name :: String | rest }
242+ -> { name :: Identifier | rest }
223243 -> String
224−showTypeClassMemberSignature { type: ty, typeClass, typeClassArguments } result =
225− yellow result.name <>
244+showTypeClassMemberSignature { "type": ty, typeClass, typeClassArguments } result =
245+ yellow (unwrap result.name) <>
226246 syntax " :: " <>
227247 showType ty
228248
@@ -231,7 +251,7 @@ showDataSignature
231251 :: forall rest
232252 . { typeArguments :: Array TypeArgument
233253 , dataDeclType :: DataDeclType }
234− -> { name :: String | rest }
254+ -> { name :: Identifier | rest }
235255 -> String
236256showDataSignature { typeArguments, dataDeclType } { name } =
237257 ( keyword
@@ -240,7 +260,7 @@ showDataSignature { typeArguments, dataDeclType } { name } =
240260 DataDataDecl -> "data"
241261 ) <>
242262 space <>
243− yellow name <>
263+ yellow (unwrap name) <>
244264 space <> (
245265 Array.intercalate space $
246266 typeArguments <#> showTypeArgument
@@ -252,12 +272,12 @@ showTypeSynonymSignature
252272 . { type :: Type
253273 , arguments :: Array TypeArgument
254274 }
255− -> { name :: String | rest }
275+ -> { name :: Identifier | rest }
256276 -> String
257277showTypeSynonymSignature { type: ty, arguments } { name } =
258278 keyword "type" <>
259279 space <>
260− yellow name <>
280+ yellow (unwrap name) <>
261281 space <> (
262282 Array.intercalate space $
263283 arguments <#> showTypeArgument
@@ -270,16 +290,38 @@ showTypeSynonymSignature { type: ty, arguments } { name } =
270290
271291showExternDataSignature
272292 :: forall rest
273− . { kind :: Kind }
274− -> { name :: String | rest }
293+ . { kind :: Type }
294+ -> { name :: Identifier | rest }
275295 -> String
276296showExternDataSignature { kind } { name } =
277297 keyword "foreign data" <>
278298 space <>
279− yellow name <>
280− space <>
299+ yellow (unwrap name) <>
281300 syntax " :: " <>
282− showKind kind
301+ showType kind
302+
303+
304+showDataConstructorSignature
305+ :: forall rest
306+ . { dataDeclType :: DataDeclType
307+ , "type" :: Type
308+ }
309+ -> { name :: Identifier
310+ | rest
311+ }
312+ -> String
313+showDataConstructorSignature { dataDeclType, type: ctorType } { name } =
314+ ( keyword
315+ case dataDeclType of
316+ NewtypeDataDecl -> "newtype constructor"
317+ DataDataDecl -> "data constructor"
318+ ) <>
319+ space <>
320+ yellow (unwrap name) <>
321+ space <>
322+ syntax "::" <>
323+ space <>
324+ showType ctorType
283325
284326
285327leftShift :: Int -> String -> String
src/Docs/Search/Loader.jsnew file+26
@@ -0,0 +1,26 @@
1+/* global exports */
2+
3+export function loadFromScript (globalIdentifier) {
4+ return function (url) {
5+ return function () {
6+ return new Promise(function (resolve, reject) {
7+ if (typeof window[globalIdentifier] === 'undefined') {
8+ var script = document.createElement('script');
9+ script.type = 'text/javascript';
10+ script.src = url;
11+ script.addEventListener('load', function () {
12+ if (typeof window[globalIdentifier] === 'undefined') {
13+ reject(new Error("Couldn't load package index."));
14+ } else {
15+ resolve(window[globalIdentifier]);
16+ }
17+ });
18+ script.addEventListener('error', reject);
19+ document.body.appendChild(script);
20+ } else {
21+ resolve(window[globalIdentifier]);
22+ }
23+ });
24+ };
25+ };
26+};
src/Docs/Search/Loader.pursnew file+38
@@ -0,0 +1,38 @@
1+module Docs.Search.Loader where
2+
3+import Docs.Search.Types (GlobalIdentifier, URL)
4+
5+import Prelude
6+
7+import Control.Monad.Error.Class (throwError)
8+import Control.Promise (Promise, toAffE)
9+import Data.Argonaut.Core (Json)
10+import Data.Argonaut.Decode.Error (printJsonDecodeError)
11+import Data.Argonaut.Decode.Class (class DecodeJson, decodeJson)
12+import Data.Either (either)
13+import Data.Newtype (unwrap)
14+import Effect (Effect)
15+import Effect.Aff (Aff)
16+import Effect.Exception (error)
17+
18+
19+
20+load
21+ :: forall a
22+ . DecodeJson a
23+ => GlobalIdentifier
24+ -> URL
25+ -> Aff a
26+load globalIdentifier url = do
27+ json <- toAffE (loadFromScript globalIdentifier url)
28+ either throw pure $ decodeJson json
29+ where
30+ throw err = throwError $ error $
31+ "Couldn't load content from window." <>
32+ unwrap globalIdentifier <> ": " <> printJsonDecodeError err
33+
34+
35+foreign import loadFromScript
36+ :: GlobalIdentifier
37+ -> URL
38+ -> Effect (Promise Json)
src/Docs/Search/Main.purs+45−34
@@ -1,17 +1,19 @@
11-- | The main module of the CLI interface app.
22module Docs.Search.Main where
33
4−import Prelude
5−
4+import Docs.Search.Config as Config
65import Docs.Search.IndexBuilder as IndexBuilder
76import Docs.Search.Interactive as Interactive
8−import Docs.Search.Config (config)
7+import Docs.Search.Types (PackageName(..))
8+
9+import Prelude
910
1011import Data.Generic.Rep (class Generic)
11−import Data.Generic.Rep.Show (genericShow)
1212import Data.List as List
1313import Data.List.NonEmpty as NonEmpty
1414import Data.Maybe (Maybe, fromMaybe, optional)
15+import Data.Newtype (unwrap)
16+import Data.Show.Generic (genericShow)
1517import Data.Unfoldable (class Unfoldable)
1618import Effect (Effect)
1719import Effect.Console (log)
@@ -23,13 +25,16 @@ main :: Effect Unit
2325main = do
2426
2527 args <- getArgs
26− let defaultCommands = Search { docsFiles: defaultDocsFiles, bowerFiles: defaultBowerFiles }
28+ let defaultCommands = Search { docsFiles: defaultDocsFiles
29+ , bowerFiles: defaultBowerFiles
30+ , packageName: Config.defaultPackageName
31+ , sourceFiles: defaultSourceFiles
32+ }
2733
2834 case fromMaybe defaultCommands args of
2935 BuildIndex cfg -> IndexBuilder.run cfg
3036 Search cfg -> Interactive.run cfg
31− Version -> log config.version
32−
37+ Version -> log Config.version
3338
3439getArgs :: Effect (Maybe Commands)
3540getArgs = execParser opts
@@ -40,27 +45,16 @@ getArgs = execParser opts
4045 <> progDesc "Search frontend for the documentation generated by the PureScript compiler."
4146 )
4247
43−
4448data Commands
45− = BuildIndex
46− { docsFiles :: Array String
47− , bowerFiles :: Array String
48− , generatedDocs :: String
49− , noPatch :: Boolean
50− }
51− | Search
52− { docsFiles :: Array String
53− , bowerFiles :: Array String
54− }
49+ = BuildIndex IndexBuilder.Config
50+ | Search Interactive.Config
5551 | Version
5652
57−
5853derive instance genericCommands :: Generic Commands _
5954
6055instance showCommands :: Show Commands where
6156 show = genericShow
6257
63−
6458commands :: Parser (Maybe Commands)
6559commands = optional $ subparser
6660 ( command "build-index"
@@ -83,34 +77,30 @@ commands = optional $ subparser
8377
8478buildIndex :: Parser Commands
8579buildIndex = ado
86−
8780 docsFiles <- docsFilesOption
88−
8981 bowerFiles <- bowerFilesOption
90−
82+ packageName <- packageNameOption
83+ sourceFiles <- sourceFilesOption
9184 generatedDocs <- strOption
9285 ( long "generated-docs"
9386 <> metavar "DIR"
9487 <> value "./generated-docs/"
88+ <> help "Path to the generated documentation HTML that will be patched. Search app will be injected into each HTML document."
9589 )
96−
9790 noPatch <- flag false true
9891 ( long "no-patch"
9992 <> help "Do not patch the HTML docs, only build indices"
10093 )
101−
102− in BuildIndex { docsFiles, bowerFiles, generatedDocs, noPatch }
94+ in BuildIndex { docsFiles, bowerFiles, generatedDocs, noPatch, packageName, sourceFiles }
10395
10496
10597startInteractive :: Parser Commands
10698startInteractive = ado
107−
10899 docsFiles <- docsFilesOption
109−
110100 bowerFiles <- bowerFilesOption
111−
112− in Search { docsFiles, bowerFiles }
113−
101+ packageName <- packageNameOption
102+ sourceFiles <- sourceFilesOption
103+ in Search { docsFiles, bowerFiles, packageName, sourceFiles }
114104
115105docsFilesOption :: Parser (Array String)
116106docsFilesOption = fromMaybe defaultDocsFiles <$>
@@ -119,11 +109,11 @@ docsFilesOption = fromMaybe defaultDocsFiles <$>
119109 ( strOption
120110 ( long "docs-files"
121111 <> metavar "GLOB"
112+ <> help "Glob that captures `docs.json` files that should be used to build the index"
122113 )
123114 )
124115 )
125116
126−
127117bowerFilesOption :: Parser (Array String)
128118bowerFilesOption = fromMaybe defaultBowerFiles <$>
129119 optional
@@ -131,22 +121,43 @@ bowerFilesOption = fromMaybe defaultBowerFiles <$>
131121 ( strOption
132122 ( long "bower-jsons"
133123 <> metavar "GLOB"
124+ <> help "Glob that captures `bower.json` files. These files are used to build dependency trees to compute package popularity scores based on how many dependants a package has."
134125 )
135126 )
136127 )
137128
129+packageNameOption :: Parser PackageName
130+packageNameOption =
131+ PackageName <$> strOption
132+ ( long "package-name"
133+ <> metavar "PACKAGE"
134+ <> value (unwrap Config.defaultPackageName)
135+ <> help "Local package name as it should appear in the search results"
136+ )
137+
138+sourceFilesOption :: Parser (Array String)
139+sourceFilesOption = fromMaybe defaultSourceFiles <$>
140+ optional
141+ ( some
142+ ( strOption
143+ ( long "source-files"
144+ <> metavar "GLOB"
145+ <> help "Path to project source files, used for more precise module indexing (see #62). Default: src/**/*.purs"
146+ )
147+ )
148+ )
138149
139150defaultDocsFiles :: Array String
140151defaultDocsFiles = [ "output/**/docs.json" ]
141152
142−
143153defaultBowerFiles :: Array String
144154defaultBowerFiles = [ ".spago/*/*/bower.json", "bower_components/purescript-*/bower.json" ]
145155
156+defaultSourceFiles :: Array String
157+defaultSourceFiles = [ "src/**/*.purs" ]
146158
147159many :: forall a f. Unfoldable f => Parser a -> Parser (f a)
148160many x = CA.many x <#> List.toUnfoldable
149161
150−
151162some :: forall a f. Unfoldable f => Parser a -> Parser (f a)
152163some x = CA.some x <#> NonEmpty.toUnfoldable
src/Docs/Search/Meta.pursnew file+21
@@ -0,0 +1,21 @@
1+module Docs.Search.Meta where
2+
3+import Docs.Search.Config as Config
4+import Docs.Search.Loader as Loader
5+import Docs.Search.Types (PackageName)
6+
7+import Prelude
8+
9+import Effect.Aff (Aff, catchError)
10+
11+
12+type Meta =
13+ { localPackageName :: PackageName
14+ }
15+
16+
17+load :: Aff Meta
18+load =
19+ Loader.load Config.metaItem Config.metaLoadPath
20+ `catchError` const (pure defaultMeta)
21+ where defaultMeta = { localPackageName: Config.defaultPackageName }
src/Docs/Search/ModuleIndex.js+1−1
@@ -1,6 +1,6 @@
11/* global exports */
22
3−exports.load = function (url) {
3+export function load (url) {
44 return function () {
55 return new Promise(function (resolve, reject) {
66 if (typeof window.DocsSearchModuleIndex === 'undefined') {
src/Docs/Search/ModuleIndex.purs+36−29
@@ -1,11 +1,11 @@
11module Docs.Search.ModuleIndex where
22
3−import Docs.Search.Config (config)
3+import Docs.Search.Config as Config
44import Docs.Search.Declarations (Declarations(..))
5−import Docs.Search.SearchResult (SearchResult(..))
6−import Docs.Search.Types (ModuleName, PackageName)
75import Docs.Search.Extra (stringToList)
8−import Docs.Search.Score (Scores, normalizePackageName)
6+import Docs.Search.Score (Scores, getPackageScore)
7+import Docs.Search.SearchResult (SearchResult(..))
8+import Docs.Search.Types (ModuleName, PackageInfo(..), PackageScore)
99
1010import Prelude
1111
@@ -21,7 +21,8 @@ import Data.Lens.Record (prop)
2121import Data.List (List, (:))
2222import Data.Map (Map)
2323import Data.Map as Map
24−import Data.Maybe (fromMaybe)
24+import Data.Maybe (Maybe(..), fromMaybe)
25+import Data.Newtype (unwrap)
2526import Data.Search.Trie (Trie)
2627import Data.Search.Trie as Trie
2728import Data.Set (Set)
@@ -29,37 +30,36 @@ import Data.Set as Set
2930import Data.String.CodeUnits (toCharArray) as String
3031import Data.String.Common (split, toLower) as String
3132import Data.String.Pattern (Pattern(..))
32−import Data.Symbol (SProxy(..))
3333import Data.Traversable (foldr, for_)
3434import Data.Tuple.Nested ((/\))
3535import Effect (Effect)
3636import Effect.Aff (Aff)
37−
37+import Type.Proxy (Proxy(..))
3838
3939-- | Module index that is actually stored in a JS file.
40−type PackedModuleIndex = Map PackageName (Set ModuleName)
40+type PackedModuleIndex = Map PackageInfo (Set ModuleName)
4141
4242-- | "Expanded" module index that can be queried quickly.
43−type ModuleIndex = { packageModules :: Map PackageName (Set ModuleName)
44− , modulePackages :: Map ModuleName PackageName
43+type ModuleIndex = { packageModules :: Map PackageInfo (Set ModuleName)
44+ , modulePackages :: Map ModuleName PackageInfo
4545 , index :: Trie Char ModuleName
4646 }
4747
4848
4949type ModuleResult
5050 = { name :: ModuleName
51− , package :: PackageName
52− , score :: Int
51+ , package :: PackageInfo
52+ , score :: PackageScore
5353 }
5454
5555
5656unpackModuleIndex :: PackedModuleIndex -> ModuleIndex
5757unpackModuleIndex packageModules =
58− flip execState { packageModules, modulePackages: mempty, index: mempty } do
58+ flip execState { packageModules, modulePackages: Map.empty, index: mempty } do
5959 for_ (Map.toUnfoldableUnordered packageModules :: Array _)
60− \(packageName /\ moduleNames) -> do
60+ \(package /\ moduleNames) -> do
6161 for_ moduleNames \moduleName -> do
62− modify_ $ _modulePackages %~ Map.insert moduleName packageName
62+ modify_ $ _modulePackages %~ Map.insert moduleName package
6363 for_ (extractModuleNameParts moduleName) \part -> do
6464 let partPath = Array.toUnfoldable $ String.toCharArray part
6565 modify_ $ _index %~ Trie.insert partPath moduleName
@@ -68,7 +68,9 @@ unpackModuleIndex packageModules =
6868-- | E.g. `"Data.Array.ST" -> ["data.array.st", "array.st", "st"]`.
6969extractModuleNameParts :: ModuleName -> List String
7070extractModuleNameParts =
71− foldl (\acc el -> el : map (_ <> "." <> el) acc) mempty <<< String.split (Pattern ".") <<< String.toLower
71+ unwrap >>> String.toLower >>>
72+ String.split (Pattern ".") >>>
73+ foldl (\acc el -> el : map (_ <> "." <> el) acc) mempty
7274
7375
7476queryModuleIndex
@@ -83,28 +85,33 @@ queryModuleIndex scores { index, modulePackages } query =
8385 Array.nub <#>
8486 (\name -> do
8587 package <- Map.lookup name modulePackages
86− pure { name, package, score: fromMaybe 0 $ Map.lookup (normalizePackageName package) scores }) #
88+ pure { name, package
89+ , score: getPackageScore scores package }) #
8790 Array.catMaybes
8891
8992
9093-- | Constructs a mapping from packages to modules
91−mkPackedModuleIndex :: Declarations -> PackedModuleIndex
92−mkPackedModuleIndex (Declarations trie) =
93− foldr (Map.unionWith Set.union) mempty $ extract <$> Trie.values trie
94+mkPackedModuleIndex :: Declarations -> Array ModuleName -> PackedModuleIndex
95+mkPackedModuleIndex (Declarations trie) moduleNames =
96+ addLocalPackageModuleNames $
97+ foldr (Map.unionWith Set.union) Map.empty $ extract <$> Trie.values trie
9498 where
99+ -- Add modules from src/ that may not contain any definitions, only
100+ -- re-exports
101+ addLocalPackageModuleNames = flip Map.alter LocalPackage $
102+ Just <<< append (Set.fromFoldable moduleNames) <<< fromMaybe Set.empty
95103 extract
96104 :: List SearchResult
97− -> Map PackageName (Set ModuleName)
98− extract = foldr (Map.unionWith Set.union) mempty <<< map mkEntry
105+ -> Map PackageInfo (Set ModuleName)
106+ extract = foldr (Map.unionWith Set.union) Map.empty <<< map mkEntry
99107 where
100− mkEntry (SearchResult { packageName, moduleName }) =
101− Map.singleton packageName (Set.singleton moduleName)
102−
108+ mkEntry (SearchResult { packageInfo, moduleName }) =
109+ Map.singleton packageInfo (Set.singleton moduleName)
103110
104111loadModuleIndex :: Aff PackedModuleIndex
105112loadModuleIndex = do
106− json <- toAffE $ load config.moduleIndexLoadPath
107− pure $ fromMaybe mempty $ hush $ decodeJson json
113+ json <- toAffE $ load Config.moduleIndexLoadPath
114+ pure $ fromMaybe Map.empty $ hush $ decodeJson json
108115
109116
110117foreign import load
@@ -113,7 +120,7 @@ foreign import load
113120
114121
115122_modulePackages :: forall a b rest. (a -> b) -> { modulePackages :: a | rest } -> { modulePackages :: b | rest }
116−_modulePackages = prop (SProxy :: SProxy "modulePackages")
123+_modulePackages = prop (Proxy :: Proxy "modulePackages")
117124
118125_index :: forall a b rest. (a -> b) -> { index :: a | rest } -> { index :: b | rest }
119−_index = prop (SProxy :: SProxy "index")
126+_index = prop (Proxy :: Proxy "index")
src/Docs/Search/ModuleParser.pursnew file+50
@@ -0,0 +1,50 @@
1+module Docs.Search.ModuleParser where
2+
3+import Prelude
4+
5+import Control.Alt ((<|>))
6+import Data.Either (hush)
7+import Data.Foldable (intercalate)
8+import Data.Maybe (Maybe)
9+import Data.Newtype (wrap)
10+import Docs.Search.Types (ModuleName)
11+import Effect (Effect)
12+import StringParser (Parser, char, choice, fix, many, manyTill, noneOf, regex, runParser, sepBy, sepBy1, string, try, whiteSpace)
13+
14+parseModuleName :: String -> Maybe ModuleName
15+parseModuleName = map wrap <<< hush <<< runParser do
16+ void $ many whiteSpaceOrComment
17+ moduleHeader
18+
19+whiteSpaceOrComment :: Parser Unit
20+whiteSpaceOrComment =
21+ choice
22+ [ try $ multiLineComment
23+ , try $ singleLineComment
24+ , try $ void whiteSpace
25+ ]
26+
27+multiLineComment :: Parser Unit
28+multiLineComment = do
29+ void $ string "{-"
30+ void $ manyTill (void $ noneOf []) (string "-}")
31+
32+singleLineComment :: Parser Unit
33+singleLineComment = do
34+ void $ string "--"
35+ void $ manyTill (void $ noneOf ['\n']) (char '\n')
36+
37+moduleHeader :: Parser String
38+moduleHeader = do
39+ void $ string "module"
40+ void $ many whiteSpaceOrComment
41+ moduleName
42+
43+moduleName :: Parser String
44+moduleName = sepBy1 moduleNameWord (string ".") <#> intercalate "."
45+
46+moduleNameWord :: Parser String
47+moduleNameWord = do
48+ first <- regex "[A-Z]"
49+ rest <- regex "[A-Za-z0-9]*"
50+ pure $ first <> rest
src/Docs/Search/PackageIndex.jsdeleted−24
@@ -1,24 +0,0 @@
1−/* global exports */
2−
3−exports.load = function (url) {
4− return function () {
5− return new Promise(function (resolve, reject) {
6− if (typeof window.DocsSearchPackageIndex === 'undefined') {
7− var script = document.createElement('script');
8− script.type = 'text/javascript';
9− script.src = url;
10− script.addEventListener('load', function () {
11− if (typeof window.DocsSearchPackageIndex === 'undefined') {
12− reject(new Error("Couldn't load package index."));
13− } else {
14− resolve(window.DocsSearchPackageIndex);
15− }
16− });
17− script.addEventListener('error', reject);
18− document.body.appendChild(script);
19− } else {
20− resolve(window.DocsSearchPackageIndex);
21− }
22− });
23− };
24−};
src/Docs/Search/PackageIndex.purs+24−31
@@ -1,32 +1,29 @@
11module Docs.Search.PackageIndex where
22
3−import Docs.Search.Config (config)
3+import Docs.Search.Config as Config
44import Docs.Search.Extra (stringToList)
5−import Docs.Search.Score (Scores, getPackageScore, normalizePackageName)
5+import Docs.Search.Score (Scores, getPackageScoreForPackageName, normalizePackageName)
6+import Docs.Search.Types (PackageName, RawPackageName(..), PackageScore)
7+import Docs.Search.Loader as Loader
68
79import Prelude
810
9−import Control.Promise (Promise, toAffE)
10−import Data.Argonaut.Core (Json)
11−import Data.Argonaut.Decode (decodeJson)
1211import Data.Array as Array
13−import Data.Either (hush)
1412import Data.Map (Map)
1513import Data.Map as Map
16−import Data.Maybe (Maybe, fromMaybe)
14+import Data.Maybe (Maybe)
1715import Data.Newtype (unwrap)
1816import Data.Search.Trie (Trie)
1917import Data.Search.Trie as Trie
20−import Effect (Effect)
2118import Effect.Aff (Aff)
2219import Web.Bower.PackageMeta (PackageMeta(..))
2320
2421
2522type PackageResult
26− = { name :: String
23+ = { name :: PackageName
2724 , description :: Maybe String
28− , score :: Int
29− , dependencies :: Array String
25+ , score :: PackageScore
26+ , dependencies :: Array PackageName
3027 , repository :: Maybe String
3128 }
3229
@@ -39,46 +36,47 @@ mkPackageInfo :: Scores -> Array PackageMeta -> PackageInfo
3936mkPackageInfo packageScores pms =
4037 Array.fromFoldable $
4138 Map.values $
42− Array.foldr insert mempty pms
39+ Array.foldr insert Map.empty pms
4340
4441 where
4542 insert
4643 :: PackageMeta
47− -> Map String PackageResult
48− -> Map String PackageResult
44+ -> Map PackageName PackageResult
45+ -> Map PackageName PackageResult
4946 insert
5047 (PackageMeta { name
5148 , description
5249 , dependencies
5350 , devDependencies
5451 , repository }) =
55−
56− Map.insert
57− name
58− { name
52+ Map.insert
53+ packageName
54+ { name: packageName
5955 , description: description
60− , score: getPackageScore packageScores $ normalizePackageName name
61− , dependencies: unwrap dependencies <#> (_.packageName)
56+ , score: getPackageScoreForPackageName packageScores packageName
57+ , dependencies:
58+ unwrap dependencies <#>
59+ _.packageName >>> RawPackageName >>> normalizePackageName
6260 , repository: repository <#> (_.url)
6361 }
6462
63+ where packageName = normalizePackageName $ RawPackageName name
6564
6665mkScoresFromPackageIndex :: PackageIndex -> Scores
6766mkScoresFromPackageIndex =
68− Trie.values >>> Array.foldr (\ { name, score } -> Map.insert name score) mempty
67+ Trie.values >>> Array.fromFoldable >>>
68+ Array.foldr (\ { name, score } -> Map.insert name score) Map.empty
6969
7070
7171loadPackageIndex :: Aff PackageIndex
72−loadPackageIndex = do
73− json <- toAffE (load config.packageInfoLoadPath)
74− let packageInfo = fromMaybe mempty $ hush $ decodeJson json
75− pure $ mkPackageIndex packageInfo
72+loadPackageIndex =
73+ mkPackageIndex <$> Loader.load Config.packageInfoItem Config.packageInfoLoadPath
7674
7775
7876mkPackageIndex :: PackageInfo -> PackageIndex
7977mkPackageIndex =
8078 Array.foldr
81− (\package -> Trie.insert (stringToList $ normalizePackageName package.name) package)
79+ (\package -> Trie.insert (stringToList $ unwrap package.name) package)
8280 mempty
8381
8482
@@ -94,8 +92,3 @@ queryPackageIndex index query =
9492 pure { index
9593 , results: Array.fromFoldable $ Trie.queryValues (stringToList query) index
9694 }
97−
98−
99−foreign import load
100− :: String
101− -> Effect (Promise Json)
src/Docs/Search/Score.purs+20−15
@@ -1,6 +1,6 @@
11module Docs.Search.Score where
22
3−import Docs.Search.Types (PackageName)
3+import Docs.Search.Types (RawPackageName(..), PackageName(..), PackageInfo(..), PackageScore(..))
44
55import Prelude
66
@@ -13,18 +13,11 @@ import Data.String.CodeUnits as String
1313import Web.Bower.PackageMeta (Dependencies, PackageMeta)
1414
1515
16−type Scores = Map PackageName Int
16+type Scores = Map PackageName PackageScore
1717
18−
19−getPackageScore :: Scores -> PackageName -> Int
20−getPackageScore _ "<builtin>" = 1000000
21−getPackageScore _ "<local package>" = 2000000
22−getPackageScore scores name = fromMaybe 0 $ Map.lookup name scores
23−
24−
25−normalizePackageName :: PackageName -> PackageName
26−normalizePackageName packageName =
27− fromMaybe packageName $ String.stripPrefix (wrap "purescript-") packageName
18+normalizePackageName :: RawPackageName -> PackageName
19+normalizePackageName (RawPackageName p) =
20+ fromMaybe (PackageName p) $ map wrap $ String.stripPrefix (wrap "purescript-") p
2821
2922
3023-- | Construct a mapping from package names to their scores, based on number
@@ -36,12 +29,24 @@ mkScores =
3629 updateScoresFor (unwrap pm).dependencies >>>
3730 updateScoresFor (unwrap pm).devDependencies
3831 )
39− mempty
32+ Map.empty
4033
4134 where
4235 updateScoresFor :: Dependencies -> Scores -> Scores
4336 updateScoresFor deps scores =
4437 Array.foldr
45− (\dep -> Map.insertWith add dep 1)
38+ (\dep -> Map.insertWith add dep one)
4639 scores
47− (deps # unwrap >>> map (_.packageName >>> normalizePackageName))
40+ (deps # unwrap >>> map (_.packageName >>> RawPackageName >>> normalizePackageName))
41+
42+
43+getPackageScore :: Scores -> PackageInfo -> PackageScore
44+getPackageScore scores = case _ of
45+ Package p -> getPackageScoreForPackageName scores p
46+ Builtin -> PackageScore 100000
47+ LocalPackage -> PackageScore 200000
48+ UnknownPackage -> zero
49+
50+
51+getPackageScoreForPackageName :: Scores -> PackageName -> PackageScore
52+getPackageScoreForPackageName scores p = fromMaybe zero $ Map.lookup p scores
src/Docs/Search/SearchResult.purs+12−10
@@ -1,14 +1,15 @@
11module Docs.Search.SearchResult where
22
33import Docs.Search.DocsJson (DataDeclType)
4−import Docs.Search.TypeDecoder (Constraint, FunDeps, Kind, QualifiedName, Type, TypeArgument)
4+import Docs.Search.TypeDecoder (Constraint, FunDeps, QualifiedName, Type, TypeArgument)
5+import Docs.Search.Types (ModuleName, PackageInfo, Identifier, PackageScore)
56
67import Prelude
7−
8+import Prim hiding (Type, Constraint)
89import Data.Argonaut.Decode (class DecodeJson)
9−import Data.Argonaut.Decode.Generic.Rep (genericDecodeJson)
10+import Data.Argonaut.Decode.Generic (genericDecodeJson)
1011import Data.Argonaut.Encode (class EncodeJson)
11−import Data.Argonaut.Encode.Generic.Rep (genericEncodeJson)
12+import Data.Argonaut.Encode.Generic (genericEncodeJson)
1213import Data.Generic.Rep (class Generic)
1314import Data.Maybe (Maybe(..))
1415import Data.Newtype (class Newtype, un)
@@ -18,10 +19,11 @@ import Data.Newtype (class Newtype, un)
1819data ResultInfo
1920 = DataResult { typeArguments :: Array TypeArgument
2021 , dataDeclType :: DataDeclType }
21− | ExternDataResult { kind :: Kind }
22+ | ExternDataResult { kind :: Type }
2223 | TypeSynonymResult { arguments :: Array TypeArgument
2324 , type :: Type }
24− | DataConstructorResult { arguments :: Array Type }
25+ | DataConstructorResult { dataDeclType :: DataDeclType
26+ , type :: Type }
2527 | TypeClassMemberResult { type :: Type
2628 , typeClass :: QualifiedName
2729 , typeClassArguments :: Array TypeArgument }
@@ -56,12 +58,12 @@ typeOf _ = Nothing
5658-- | Common metadata for all types of search results.
5759newtype SearchResult
5860 = SearchResult
59− { name :: String
61+ { name :: Identifier
6062 , comments :: Maybe String
6163 , hashAnchor :: String
62− , moduleName :: String
63− , packageName :: String
64− , score :: Int
64+ , moduleName :: ModuleName
65+ , packageInfo :: PackageInfo
66+ , score :: PackageScore
6567 , sourceSpan :: Maybe { start :: Array Int
6668 , end :: Array Int
6769 , name :: String
src/Docs/Search/TypeDecoder.purs+46−78
@@ -1,18 +1,21 @@
1+-- | A decoder for types located in 'Language.PureScript.Types'.
12module Docs.Search.TypeDecoder where
23
3−import Prelude
4+import Docs.Search.Types (Identifier)
45
6+import Prelude
7+import Prim hiding (Type, Constraint)
58import Control.Alt ((<|>))
69import Data.Argonaut.Core (Json, caseJsonObject, fromArray, fromObject, jsonEmptyObject, stringify, toArray)
710import Data.Argonaut.Decode (class DecodeJson, decodeJson, (.:))
811import Data.Argonaut.Encode (class EncodeJson, encodeJson)
9−import Data.Array ((!!))
12+import Data.Argonaut.Decode.Error (JsonDecodeError(..))
1013import Data.Either (Either(..))
1114import Data.Generic.Rep (class Generic)
12−import Data.Generic.Rep.Show (genericShow)
15+import Data.Show.Generic (genericShow)
1316import Data.List (List(..), (:))
1417import Data.List as List
15−import Data.Maybe (Maybe(..), fromMaybe)
18+import Data.Maybe (Maybe(..))
1619import Data.Newtype (class Newtype)
1720import Data.Tuple (Tuple(..))
1821import Foreign.Object as Object
@@ -25,71 +28,28 @@ instance showQualifiedName :: Show QualifiedName where
2528 show = genericShow
2629
2730newtype QualifiedName
28− = QualifiedName { moduleName :: Array String
29− , name :: String
31+ = QualifiedName { moduleNameParts :: Array String
32+ , name :: Identifier
3033 }
3134
3235instance decodeJsonQualifiedName :: DecodeJson QualifiedName where
3336 decodeJson json = do
3437 decodeTuple
35− (\moduleName name -> QualifiedName { moduleName, name })
38+ (\moduleNameParts name -> QualifiedName { moduleNameParts, name })
3639 (mkJsonError "QualifiedName" json)
3740 json
3841
3942instance encodeJsonQualifiedName :: EncodeJson QualifiedName where
40− encodeJson (QualifiedName { moduleName, name }) =
41− encodeTuple moduleName name
43+ encodeJson (QualifiedName { moduleNameParts, name }) =
44+ encodeTuple moduleNameParts name
4245
43−mkJsonError :: String -> Json -> (forall i. i -> String)
46+mkJsonError :: String -> Json -> (forall i. i -> JsonDecodeError)
4447mkJsonError name json _ =
45− "Couldn't parse " <> name <> " from " <> stringify json
48+ TypeMismatch $ "Couldn't parse " <> name <> " from " <> stringify json
4649
47−mkJsonError' :: String -> Json -> String
50+mkJsonError' :: String -> Json -> JsonDecodeError
4851mkJsonError' name json = mkJsonError name json unit
4952
50−-- | The data type of kinds
51−data Kind
52− -- | Kinds for labelled, unordered rows without duplicates
53− = Row Kind
54− -- | Function kinds
55− | FunKind Kind Kind
56− -- | A named kind
57− | NamedKind QualifiedName
58−
59−derive instance eqKind :: Eq Kind
60−derive instance genericKind :: Generic Kind _
61−
62−instance showKind :: Show Kind where
63− show x = genericShow x
64−
65−instance decodeJsonKind :: DecodeJson Kind where
66− decodeJson json = do
67− handle <- decodeJson json
68− tag <- handle .: "tag"
69− case tag of
70− "NamedKind" -> do
71− contents <- handle .: "contents"
72− pure $ NamedKind contents
73− "Row" -> do
74− contents <- handle .: "contents"
75− pure $ Row contents
76− "FunKind" -> do
77− contents <- handle .: "contents"
78− case contents of
79− [k1, k2] ->
80− Right $ FunKind k1 k2
81− _ -> Left $ mkJsonError' "FunKind" json
82− _ -> Left $ mkJsonError' "Kind" json
83−
84−instance encodeJsonKind :: EncodeJson Kind where
85− encodeJson = case _ of
86− Row k ->
87− tagged "Row" (encodeJson k)
88− FunKind k1 k2 ->
89− tagged "FunKind" (encodeTuple k1 k2)
90− NamedKind qname ->
91− tagged "NamedKind" (encodeJson qname)
92−
9353-- | A typeclass constraint
9454newtype Constraint = Constraint
9555 { constraintClass :: QualifiedName
@@ -138,8 +98,10 @@ data Type
13898 | TypeOp QualifiedName
13999 -- | A type application
140100 | TypeApp Type Type
101+ -- | Explicit kind application
102+ | KindApp Type Type
141103 -- | Forall quantifier
142− | ForAll String (Maybe Kind) Type
104+ | ForAll String (Maybe Type) Type
143105 -- | A type withset of type class constraints
144106 | ConstrainedType Constraint Type
145107 {-
@@ -149,11 +111,9 @@ data Type
149111 -- | An empty row
150112 | REmpty
151113 -- | A non-empty row
152− | RCons String Type Type
153− {-
114+ | RCons Identifier Type Type
154115 -- | A type with a kind annotation
155− | Kinded Type Kind
156− -}
116+ | Kinded Type Type
157117 -- | Binary operator application. During the rebracketing phase of desugaring,
158118 -- this data constructor will be removed.
159119 | BinaryNoParensType Type Type Type
@@ -179,6 +139,9 @@ instance decodeJsonType :: DecodeJson Type where
179139 "TypeApp" ->
180140 decodeContents (decodeTuple TypeApp (const err)) (Left err) json
181141 where err = mkJsonError' "TypeApp" json
142+ "KindApp" ->
143+ decodeContents (decodeTuple KindApp (const err)) (Left err) json
144+ where err = mkJsonError' "KindApp" json
182145 "ForAll" ->
183146 decodeContents
184147 (decodeTriple
@@ -187,9 +150,10 @@ instance decodeJsonType :: DecodeJson Type where
187150 (Left $ err unit)
188151 json
189152 <|>
153+ -- Ignore SkolemScope
190154 decodeContents
191155 (decodeQuadriple
192− (\f (k :: Kind) a (_ :: Maybe Int) ->
156+ (\f (k :: Type) a (_ :: Maybe Int) ->
193157 ForAll f (Just k) a)
194158 err)
195159 (Left $ err unit)
@@ -202,6 +166,9 @@ instance decodeJsonType :: DecodeJson Type where
202166 "RCons" ->
203167 decodeContents (decodeTriple RCons (const err)) (Left err) json
204168 where err = mkJsonError' "RCons" json
169+ "KindedType" ->
170+ decodeContents (decodeTuple Kinded (const err)) (Left err) json
171+ where err = mkJsonError' "KindedType" json
205172 "BinaryNoParensType" ->
206173 decodeContents (decodeTriple BinaryNoParensType (const err)) (Left err) json
207174 where err = mkJsonError' "BinaryNoParens" json
@@ -219,11 +186,13 @@ instance encodeJsonType :: EncodeJson Type where
219186 TypeConstructor val -> tagged "TypeConstructor" (encodeJson val)
220187 TypeOp val -> tagged "TypeOp" (encodeJson val)
221188 TypeApp t1 t2 -> tagged "TypeApp" (encodeTuple t1 t2)
189+ KindApp t1 t2 -> tagged "KindApp" (encodeTuple t1 t2)
222190 ForAll str Nothing ty -> tagged "ForAll" (encodeTriple str ty emptySkolemScope)
223191 ForAll str (Just k) ty -> tagged "ForAll" (encodeQuadriple str k ty emptySkolemScope)
224192 ConstrainedType c t -> tagged "ConstrainedType" (encodeTuple c t)
225193 REmpty -> tagged "REmpty" jsonEmptyObject
226194 RCons s t1 t2 -> tagged "RCons" (encodeTriple s t1 t2)
195+ Kinded t1 t2 -> tagged "KindedType" (encodeTuple t1 t2)
227196 ParensInType t -> tagged "ParensInType" (encodeJson t)
228197 TypeWildcard -> tagged "TypeWildcard" jsonEmptyObject
229198 BinaryNoParensType t1 t2 t3 ->
@@ -268,7 +237,7 @@ instance encodeJsonFunDeps :: EncodeJson FunDeps where
268237newtype TypeArgument
269238 = TypeArgument
270239 { name :: String
271− , mbKind :: Maybe Kind
240+ , mbKind :: Maybe Type
272241 }
273242
274243derive newtype instance eqTypeArgument :: Eq TypeArgument
@@ -292,17 +261,16 @@ decodeTuple
292261 . DecodeJson fst
293262 => DecodeJson sec
294263 => (fst -> sec -> res)
295− -> (forall a. a -> String)
264+ -> (forall a. a -> JsonDecodeError)
296265 -> Json
297− -> Either String res
266+ -> Either JsonDecodeError res
298267decodeTuple cont err json =
299− fromMaybe (Left $ err unit) $
300− toArray json >>= \jsons ->
301− jsons !! 0 >>= \json1 ->
302− jsons !! 1 >>= \json2 -> pure $ do
303− fst <- decodeJson json1
304− sec <- decodeJson json2
305− pure $ cont fst sec
268+ case toArray json of
269+ Just [ json1, json2 ] -> do
270+ fst <- decodeJson json1
271+ sec <- decodeJson json2
272+ pure $ cont fst sec
273+ _ -> Left $ err unit
306274
307275-- | Decode a heterogeneous triple.
308276decodeTriple
@@ -311,9 +279,9 @@ decodeTriple
311279 => DecodeJson sec
312280 => DecodeJson trd
313281 => (fst -> sec -> trd -> res)
314− -> (forall a. a -> String)
282+ -> (forall a. a -> JsonDecodeError)
315283 -> Json
316− -> Either String res
284+ -> Either JsonDecodeError res
317285decodeTriple cont err json =
318286 case toArray json of
319287 Just [ json1, json2, json3 ] -> do
@@ -331,9 +299,9 @@ decodeQuadriple
331299 => DecodeJson trd
332300 => DecodeJson frt
333301 => (fst -> sec -> trd -> frt -> res)
334− -> (forall a. a -> String)
302+ -> (forall a. a -> JsonDecodeError)
335303 -> Json
336− -> Either String res
304+ -> Either JsonDecodeError res
337305decodeQuadriple cont err json =
338306 case toArray json of
339307 Just [ json1, json2, json3, json4 ] -> do
@@ -403,7 +371,7 @@ tagged tag contents =
403371joinForAlls
404372 :: Type
405373 -> { binders :: List { name :: String
406− , mbKind :: Maybe Kind }
374+ , mbKind :: Maybe Type }
407375 , ty :: Type
408376 }
409377joinForAlls ty = go Nil ty
@@ -412,7 +380,7 @@ joinForAlls ty = go Nil ty
412380 go ({ name, mbKind } : acc) ty'
413381 go acc ty' = { binders: acc, ty: ty' }
414382
415−joinRows :: Type -> { rows :: List { row :: String
383+joinRows :: Type -> { rows :: List { row :: Identifier
416384 , ty :: Type
417385 }
418386 , ty :: Maybe Type }
@@ -428,7 +396,7 @@ joinRows = go Nil
428396 }
429397
430398-- | Only returns a list of type class names (lists of arguments are omitted).
431−joinConstraints :: Type -> { constraints :: List String
399+joinConstraints :: Type -> { constraints :: List Identifier
432400 , ty :: Type }
433401joinConstraints = go Nil
434402 where
src/Docs/Search/TypeIndex.js+1−1
@@ -1,6 +1,6 @@
11/* global exports */
22
3−exports.lookup_ = function (shape) {
3+export function lookup_ (shape) {
44 return function (url) {
55 return function () {
66 return new Promise(function (resolve, reject) {
src/Docs/Search/TypeIndex.purs+11−10
@@ -1,40 +1,40 @@
11-- | Partial type index, can be loaded on demand in the browser.
22module Docs.Search.TypeIndex where
33
4−import Docs.Search.Config (config)
4+import Docs.Search.Config as Config
55import Docs.Search.Declarations (resultsForDeclaration)
66import Docs.Search.DocsJson (DocsJson(..))
77import Docs.Search.Score (Scores)
88import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
99import Docs.Search.TypeDecoder (Type)
1010import Docs.Search.TypeQuery (TypeQuery)
11+import Docs.Search.Types (ModuleName(..))
1112import Docs.Search.TypeShape (shapeOfType, shapeOfTypeQuery, stringifyShape)
1213
1314import Prelude
14−
15+import Prim hiding (Type)
1516import Control.Promise (Promise, toAffE)
1617import Data.Argonaut.Core (Json)
1718import Data.Argonaut.Decode (decodeJson)
1819import Data.Array as Array
1920import Data.Either (hush)
21+import Data.Foldable (fold, foldr)
2022import Data.Map (Map)
2123import Data.Map as Map
2224import Data.Maybe (Maybe(..), fromMaybe', isJust)
23−import Data.Newtype (class Newtype, unwrap, wrap)
25+import Data.Newtype (class Newtype, over)
2426import Effect (Effect)
2527import Effect.Aff (Aff, try)
2628
2729
2830newtype TypeIndex = TypeIndex (Map String (Maybe (Array SearchResult)))
2931
30−derive newtype instance semigroupTypeIndex :: Semigroup TypeIndex
31−derive newtype instance monoidTypeIndex :: Monoid TypeIndex
3232derive instance newtypeTypeIndex :: Newtype TypeIndex _
3333
3434
3535mkTypeIndex :: Scores -> Array DocsJson -> TypeIndex
3636mkTypeIndex scores docsJsons =
37− TypeIndex $ map Just $ Array.foldr insert mempty docsJsons
37+ TypeIndex $ map Just $ foldr insert Map.empty docsJsons
3838 where
3939 insert :: DocsJson -> Map String (Array SearchResult) -> Map String (Array SearchResult)
4040 insert docsJson mp =
@@ -48,7 +48,8 @@ mkTypeIndex scores docsJsons =
4848
4949allResults :: Scores -> DocsJson -> Array SearchResult
5050allResults scores (DocsJson { name, declarations }) =
51− declarations >>= (resultsForDeclaration scores name >>> map (_.result) >>> Array.fromFoldable)
51+ declarations >>= (resultsForDeclaration scores (ModuleName name) >>>
52+ map (_.result) >>> Array.fromFoldable)
5253
5354
5455resultsWithTypes :: Scores -> DocsJson -> Array SearchResult
@@ -76,9 +77,9 @@ lookup
7677 -> Aff { index :: TypeIndex, results :: Array SearchResult }
7778lookup key index@(TypeIndex map) =
7879 case Map.lookup key map of
79− Just results -> pure { index, results: Array.fold results }
80+ Just results -> pure { index, results: fold results }
8081 Nothing -> do
81− eiJson <- try (toAffE (lookup_ key $ config.mkShapeScriptPath key))
82+ eiJson <- try (toAffE (lookup_ key $ Config.mkShapeScriptPath key))
8283 pure $ fromMaybe'
8384 (\_ -> { index: insert key Nothing index, results: [] })
8485 do
@@ -92,7 +93,7 @@ lookup key index@(TypeIndex map) =
9293 -> Maybe (Array SearchResult)
9394 -> TypeIndex
9495 -> TypeIndex
95− insert k v = unwrap >>> Map.insert k v >>> wrap
96+ insert k v = over TypeIndex (Map.insert k v)
9697
9798
9899query
src/Docs/Search/TypePrinter.purs+19−21
@@ -1,14 +1,16 @@
11module Docs.Search.TypePrinter where
22
33import Prelude
4−
4+import Prim hiding (Type, Constraint)
55import Docs.Search.Extra ((>#>))
66import Docs.Search.Terminal (cyan)
7−import Docs.Search.TypeDecoder (Constraint(..), FunDep(..), FunDeps(..), Kind(..), QualifiedName(..), Type(..), TypeArgument(..), joinForAlls, joinRows)
7+import Docs.Search.TypeDecoder (Constraint(..), FunDep(..), FunDeps(..), QualifiedName(..), Type(..), TypeArgument(..), joinForAlls, joinRows)
8+import Docs.Search.Types (Identifier(..))
89
9−import Data.Maybe (Maybe(..), fromMaybe)
1010import Data.Array as Array
1111import Data.List as List
12+import Data.Maybe (Maybe(..), fromMaybe)
13+import Data.Newtype (unwrap)
1214
1315
1416-- | A pretty-printer for types, for TTY with colors.
@@ -21,20 +23,23 @@ showType = case _ of
2123 TypeOp qname -> showQualifiedName qname
2224
2325 TypeApp (TypeApp (TypeConstructor
24− (QualifiedName { moduleName: [ "Prim" ]
25− , name: "Function" }))
26+ (QualifiedName { moduleNameParts: [ "Prim" ]
27+ , name: Identifier "Function" }))
2628 t1)
2729 t2 ->
2830 showType t1 <> syntax " -> " <> showType t2
2931
30− TypeApp (TypeConstructor (QualifiedName { moduleName: [ "Prim" ]
31− , name: "Record" }))
32+ TypeApp (TypeConstructor (QualifiedName { moduleNameParts: [ "Prim" ]
33+ , name: Identifier "Record" }))
3234 row ->
3335 showRow false row
3436
3537 TypeApp t1 t2 ->
3638 showType t1 <> " " <> showType t2
3739
40+ KindApp t1 t2 ->
41+ showType t1 <> " " <> showType t2
42+
3843 ty@(ForAll _ _ _) ->
3944 showForAll ty
4045
@@ -46,6 +51,8 @@ showType = case _ of
4651 ty@REmpty -> showRow true ty
4752 ty@(RCons _ _ _) -> showRow true ty
4853
54+ Kinded t1 t2 -> showType t1 <> " :: " <> showType t2
55+
4956 BinaryNoParensType op t1 t2 ->
5057 showType t1 <>
5158 space <>
@@ -68,7 +75,7 @@ showTypeArgument (TypeArgument { name, mbKind }) =
6875 "(" <>
6976 name <>
7077 " :: " <>
71− showKind kind <>
78+ showType kind <>
7279 ")"
7380
7481
@@ -89,7 +96,7 @@ showQualifiedName
8996 :: QualifiedName
9097 -> String
9198showQualifiedName (QualifiedName { name })
92− = name
99+ = unwrap name
93100
94101
95102showRow
@@ -107,7 +114,7 @@ showRow asRow =
107114 opening <>
108115 ( Array.intercalate ", " $ Array.fromFoldable $ rows <#>
109116 \entry ->
110− entry.row <> syntax " :: " <> showType entry.ty
117+ unwrap entry.row <> syntax " :: " <> showType entry.ty
111118 ) <>
112119
113120 (ty >#> \ty' -> " | " <> showType ty') <>
@@ -125,7 +132,7 @@ showForAll
125132showForAll ty =
126133 keyword "forall" <>
127134
128− ( Array.fold $ foralls.binders <#>
135+ ( Array.fold $ Array.fromFoldable $ foralls.binders <#>
129136 \ { name, mbKind } ->
130137 case mbKind of
131138 Nothing -> " " <> name
@@ -133,7 +140,7 @@ showForAll ty =
133140 " (" <> name <> " "
134141 <> syntax "::"
135142 <> space
136− <> showKind kind
143+ <> showType kind
137144 <> ")"
138145 ) <>
139146
@@ -144,15 +151,6 @@ showForAll ty =
144151 foralls = joinForAlls ty
145152
146153
147−showKind
148− :: Kind
149− -> String
150−showKind = case _ of
151− Row k1 -> "# " <> showKind k1
152− FunKind k1 k2 -> showKind k1 <> syntax " -> " <> showKind k2
153− NamedKind qname -> showQualifiedName qname
154−
155−
156154showConstraint
157155 :: Constraint
158156 -> String
src/Docs/Search/TypeQuery.purs+65−51
@@ -10,17 +10,18 @@ module Docs.Search.TypeQuery
1010 )
1111where
1212
13−import Docs.Search.Config (config)
13+import Docs.Search.Config as Config
1414import Docs.Search.Extra (foldl1, foldr1)
1515import Docs.Search.TypeDecoder (QualifiedName(..), Type(..), joinConstraints, joinRows)
16+import Docs.Search.Types (Identifier(..))
1617
1718import Prelude
18−
19+import Prim hiding (Type)
1920import Control.Alt ((<|>))
2021import Data.Array as Array
2122import Data.Either (Either)
2223import Data.Generic.Rep (class Generic)
23−import Data.Generic.Rep.Show (genericShow)
24+import Data.Show.Generic (genericShow)
2425import Data.List (List(..), many, some, (:))
2526import Data.List as List
2627import Data.List.NonEmpty (NonEmptyList)
@@ -33,21 +34,21 @@ import Data.Set as Set
3334import Data.String.CodeUnits (fromCharArray)
3435import Data.String.Common (trim) as String
3536import Data.Tuple (Tuple(..), fst, snd)
36−import Text.Parsing.StringParser (ParseError, Parser, runParser, try)
37−import Text.Parsing.StringParser.CodePoints (alphaNum, anyLetter, char, eof, lowerCaseChar, skipSpaces, string, upperCaseChar)
38−import Text.Parsing.StringParser.Combinators (fix, sepBy, sepBy1, sepEndBy, sepEndBy1)
37+import StringParser (ParseError, Parser, runParser, try)
38+import StringParser.CodePoints (alphaNum, anyLetter, char, eof, lowerCaseChar, skipSpaces, string, upperCaseChar)
39+import StringParser.Combinators (fix, sepBy, sepBy1, sepEndBy, sepEndBy1)
3940
4041
4142-- | We need type queries because we don't have a full-featured type parser
4243-- | available.
4344data TypeQuery
44− = QVar String
45− | QConst String
45+ = QVar Identifier
46+ | QConst Identifier
4647 | QFun TypeQuery TypeQuery
4748 | QApp TypeQuery TypeQuery
48− | QForAll (NonEmptyList String) TypeQuery
49− | QConstraint String (List TypeQuery) TypeQuery
50− | QRow (List (Tuple String TypeQuery))
49+ | QForAll (NonEmptyList Identifier) TypeQuery
50+ | QConstraint Identifier (List TypeQuery) TypeQuery
51+ | QRow (List (Tuple Identifier TypeQuery))
5152
5253derive instance eqTypeQuery :: Eq TypeQuery
5354derive instance genericTypeQuery :: Generic TypeQuery _
@@ -69,7 +70,8 @@ typeQueryParser = fix \typeQuery ->
6970
7071 row = string "(" *> rowFields <* string ")"
7172
72− record = QApp (QConst "Record") <$> (string "{" *> rowFields <* string "}")
73+ record = QApp (QConst $ Identifier "Record") <$>
74+ (string "{" *> rowFields <* string "}")
7375
7476 binders =
7577 string "forall" *> some space *> sepEndBy1 ident skipSpaces <* string "." <* skipSpaces
@@ -111,32 +113,32 @@ concrete :: Parser TypeQuery
111113concrete =
112114 QConst <$> upperCaseIdent
113115
114−ident :: Parser String
116+ident :: Parser Identifier
115117ident = do
116118 head <- anyLetter
117119 rest <- Array.many (alphaNum <|> char '\'')
118− pure $ fromCharArray $ pure head <> rest
120+ pure $ Identifier <$> fromCharArray $ pure head <> rest
119121
120−upperCaseIdent :: Parser String
122+upperCaseIdent :: Parser Identifier
121123upperCaseIdent = do
122124 head <- upperCaseChar
123125 rest <- Array.many (alphaNum <|> char '\'')
124− pure $ fromCharArray $ pure head <> rest
126+ pure $ Identifier $ fromCharArray $ pure head <> rest
125127
126−lowerCaseIdent :: Parser String
128+lowerCaseIdent :: Parser Identifier
127129lowerCaseIdent = do
128130 head <- lowerCaseChar
129131 rest <- Array.many (alphaNum <|> char '\'')
130− pure $ fromCharArray $ pure head <> rest
132+ pure $ Identifier $ fromCharArray $ pure head <> rest
131133
132134space :: Parser Char
133135space = char ' '
134136
135137
136138-- | Used only in `getFreeVariables`.
137−data FreeVarCounterQueueEntry = Unbind (Set.Set String) | Next TypeQuery
139+data FreeVarCounterQueueEntry = Unbind (Set.Set Identifier) | Next TypeQuery
138140
139−getFreeVariables :: TypeQuery -> Set.Set String
141+getFreeVariables :: TypeQuery -> Set.Set Identifier
140142getFreeVariables query = go Set.empty Set.empty (List.singleton $ Next query)
141143 where
142144 insertIfUnbound bound var free =
@@ -172,11 +174,11 @@ getFreeVariables query = go Set.empty Set.empty (List.singleton $ Next query)
172174
173175
174176data Substitution
175− = Instantiate String Type
176− | Match String String
177− | Generalize TypeQuery String
178− | Substitute String String
179− | MatchConstraints (Set String) (Set String)
177+ = Instantiate Identifier Type
178+ | Match Identifier Identifier
179+ | Generalize TypeQuery Identifier
180+ | Substitute Identifier Identifier
181+ | MatchConstraints (Set Identifier) (Set Identifier)
180182 | MissingConstraint
181183 | ExcessiveConstraint
182184 | RowsMismatch Int Int
@@ -225,22 +227,22 @@ unify query type_ = go Nil (List.singleton { q: query, t: type_ })
225227
226228 -- * Type variables
227229 go acc ({ q: QVar q, t: TypeVar v } : rest) =
228− go (Substitute q v : acc) rest
230+ go (Substitute q (Identifier v) : acc) rest
229231 go acc ({ q, t: TypeVar v } : rest ) =
230− go (Generalize q v : acc) rest
232+ go (Generalize q (Identifier v) : acc) rest
231233 go acc ({ q: QVar v, t } : rest) =
232234 go (Instantiate v t : acc) rest
233235
234236 -- * Names
235237 go acc ({ q: QConst qname, t: TypeConstructor (QualifiedName { name }) } : rest) =
236238 go (Match qname name : acc) rest
237− go acc ({ q: QConst qname, t } : rest) =
239+ go acc ({ q: QConst _, t } : rest) =
238240 go (TypeMismatch t : acc) rest
239− go acc ({ q, t: TypeConstructor (QualifiedName { name }) } : rest) =
241+ go acc ({ q, t: TypeConstructor (QualifiedName _) } : rest) =
240242 go (QueryMismatch q : acc) rest
241243
242244 -- type operators can't appear in type queries: this is always a mismatch
243− go acc ({ q, t: TypeOp (QualifiedName { name }) } : rest) =
245+ go acc ({ q, t: TypeOp (QualifiedName _) } : rest) =
244246 go (QueryMismatch q : acc) rest
245247 go acc ({ q, t: t@(BinaryNoParensType _ _ _) } : rest) =
246248 go (Mismatch q t : acc) rest
@@ -248,18 +250,18 @@ unify query type_ = go Nil (List.singleton { q: query, t: type_ })
248250 -- * Functions
249251 go acc ({ q: QFun q1 q2
250252 , t: TypeApp (TypeApp (TypeConstructor
251− (QualifiedName { moduleName: [ "Prim" ]
252− , name: "Function" })) t1) t2 } : rest) =
253+ (QualifiedName { moduleNameParts: [ "Prim" ]
254+ , name: Identifier "Function" })) t1) t2 } : rest) =
253255 go acc ({ q: q1, t: t1 } : { q: q2, t: t2 } : rest)
254− go acc ({ q: q@(QFun q1 q2), t } : rest) =
256+ go acc ({ q: q@(QFun _ _), t } : rest) =
255257 go (Mismatch q t : acc) rest
256258
257259 -- * Rows
258− go acc ({ q: QApp (QConst "Record") (QRow qRows)
260+ go acc ({ q: QApp (QConst (Identifier "Record")) (QRow qRows)
259261 , t: TypeApp (TypeConstructor
260− (QualifiedName { moduleName: [ "Prim" ]
261− , name: "Record" })) row } : rest) =
262− let { rows, ty } = joinRows row
262+ (QualifiedName { moduleNameParts: [ "Prim" ]
263+ , name: Identifier "Record" })) row } : rest) =
264+ let { rows } = joinRows row
263265 qRowsLength = List.length qRows
264266 rowsLength = List.length rows in
265267 if rowsLength == qRowsLength then
@@ -295,12 +297,18 @@ unify query type_ = go Nil (List.singleton { q: query, t: type_ })
295297 go acc ({ q, t: REmpty } : rest) =
296298 go (QueryMismatch q : acc) rest
297299
300+ go acc ({ q, t: Kinded _ _} : rest) =
301+ go (QueryMismatch q : acc) rest
302+
303+ go acc ({ t: t@(KindApp _ _) } : rest) =
304+ go (TypeMismatch t : acc) rest
305+
298306
299307-- | Sum various penalties.
300308penalty :: TypeQuery -> Type -> Int
301309penalty typeQuery ty =
302310 let substs = unify typeQuery ty in
303− typeVarPenalty substs * config.penalties.typeVars +
311+ typeVarPenalty substs * Config.penalties.typeVars +
304312 namesPenalty substs +
305313 mismatchPenalty substs
306314
@@ -319,14 +327,17 @@ typeVarPenalty substs =
319327 insertion v1 v2 = Map.insertWith append v1 (Set.singleton v2)
320328
321329 varSubstMapWith
322− :: (String -> String -> Map String (Set String) -> Map String (Set String))
323− -> Map String (Set String)
330+ :: (Identifier ->
331+ Identifier ->
332+ Map Identifier (Set Identifier) ->
333+ Map Identifier (Set Identifier))
334+ -> Map Identifier (Set Identifier)
324335 varSubstMapWith f =
325336 List.foldr (case _ of
326337 Substitute v1 v2 ->
327338 f v1 v2
328339 _ -> identity
329− ) mempty substs
340+ ) Map.empty substs
330341
331342
332343-- | Penalty for name mismatches.
@@ -336,12 +347,12 @@ namesPenalty = go 0
336347 go p Nil = p
337348 go p (Match a b : rest)
338349 | a == b = go p rest
339− | otherwise = go (p + config.penalties.match) rest
350+ | otherwise = go (p + Config.penalties.match) rest
340351 go p (MatchConstraints qcs tcs : rest)
341352 = let p' = Set.size (Set.union qcs tcs) -
342353 Set.size (Set.intersection qcs tcs) in
343− go (p + config.penalties.matchConstraint * p') rest
344− go p (RowsMismatch n m : rest) = go (config.penalties.rowsMismatch * abs (n - m)) rest
354+ go (p + Config.penalties.matchConstraint * p') rest
355+ go p (RowsMismatch n m : rest) = go (Config.penalties.rowsMismatch * abs (n - m)) rest
345356 go p (_ : rest) = go p rest
346357
347358
@@ -351,11 +362,11 @@ mismatchPenalty = go 0
351362 where
352363 go n Nil = n
353364 go n (Instantiate q t : rest) = go (n + typeSize t *
354− config.penalties.instantiate) rest
365+ Config.penalties.instantiate) rest
355366 go n (Generalize q t : rest) = go (n + typeQuerySize q *
356− config.penalties.generalize) rest
357− go n (ExcessiveConstraint : rest) = go (n + config.penalties.excessiveConstraint) rest
358− go n (MissingConstraint : rest) = go (n + config.penalties.missingConstraint) rest
367+ Config.penalties.generalize) rest
368+ go n (ExcessiveConstraint : rest) = go (n + Config.penalties.excessiveConstraint) rest
369+ go n (MissingConstraint : rest) = go (n + Config.penalties.missingConstraint) rest
359370 go n (Mismatch q t : rest) = go (n + typeQuerySize q + typeSize t) rest
360371 go n (TypeMismatch t : rest) = go (n + typeSize t) rest
361372 go n (QueryMismatch q : rest) = go (n + typeQuerySize q) rest
@@ -363,7 +374,7 @@ mismatchPenalty = go 0
363374
364375
365376-- | Only returns a list of type class names (lists of arguments are omitted).
366−joinQueryConstraints :: TypeQuery -> { constraints :: List String
377+joinQueryConstraints :: TypeQuery -> { constraints :: List Identifier
367378 , ty :: TypeQuery }
368379joinQueryConstraints = go Nil
369380 where
@@ -406,9 +417,10 @@ typeSize = go 0 <<< List.singleton
406417 go (n + 1) rest
407418 go n (TypeOp _ : rest) =
408419 go (n + 1) rest
420+ go n (KindApp t1 t2 : res) = go n (t1 : t2 : res)
409421 go n (TypeApp (TypeApp (TypeConstructor
410− (QualifiedName { moduleName: [ "Prim" ]
411− , name: "Function" })) t1) t2 : rest) =
422+ (QualifiedName { moduleNameParts: [ "Prim" ]
423+ , name: Identifier "Function" })) t1) t2 : rest) =
412424 go (n + 1) (t1 : t2 : rest)
413425 go n (TypeApp q1 q2 : rest) =
414426 go (n + 1) (q1 : q2 : rest)
@@ -420,6 +432,8 @@ typeSize = go 0 <<< List.singleton
420432 go (n + 1) (t1 : t2 : rest)
421433 go n (REmpty : rest) =
422434 go (n + 1) rest
435+ go n (Kinded t1 t2 : rest) =
436+ go n (t1 : t2 : rest)
423437 go n (BinaryNoParensType op t1 t2 : rest) =
424438 go (n + 1) (t1 : t2 : rest)
425439 go n (ParensInType t : rest) =
src/Docs/Search/TypeShape.js+1−1
@@ -1,6 +1,6 @@
11/* global exports */
22
3−exports.hash = function (string) {
3+export function hash (string) {
44 var hash = Math.floor(Number.MAX_SAFE_INTEGER / 2);
55 if (string.length == 0) {
66 return hash;
src/Docs/Search/TypeShape.purs+10−4
@@ -5,11 +5,12 @@ module Docs.Search.TypeShape where
55
66import Docs.Search.TypeDecoder (QualifiedName(..), Type(..), joinForAlls, joinRows)
77import Docs.Search.TypeQuery (TypeQuery(..), getFreeVariables)
8+import Docs.Search.Types (Identifier(..))
89
910import Prelude
10−
11+import Prim hiding (Type)
1112import Data.Generic.Rep (class Generic)
12−import Data.Generic.Rep.Show (genericShow)
13+import Data.Show.Generic (genericShow)
1314import Data.List (List(..), (:))
1415import Data.List as List
1516import Data.List.NonEmpty as NonEmptyList
@@ -101,8 +102,8 @@ shapeOfType ty = List.reverse $ go (pure ty) Nil
101102 TypeWildcard ->
102103 go rest (PVar : acc)
103104
104− TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Prim"]
105− , name: "Function" })) t1) t2 ->
105+ TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleNameParts: ["Prim"]
106+ , name: Identifier "Function" })) t1) t2 ->
106107 go (t1 : t2 : rest) (PFun : acc)
107108
108109 TypeConstructor (QualifiedName { name }) ->
@@ -114,6 +115,9 @@ shapeOfType ty = List.reverse $ go (pure ty) Nil
114115 TypeApp child1 child2 ->
115116 go (child1 : child2 : rest) (PApp : acc)
116117
118+ KindApp child1 child2 ->
119+ go (child1 : child2 : rest) (PApp : acc)
120+
117121 forallType@(ForAll _ _ _) ->
118122 go (foralls.ty : rest) (PForAll (List.length foralls.binders) : acc)
119123 where foralls = joinForAlls forallType
@@ -135,6 +139,8 @@ shapeOfType ty = List.reverse $ go (pure ty) Nil
135139 sorted = List.sortBy (\x y -> compare x.row y.row) joined.rows
136140 typesInRow = sorted <#> (_.ty)
137141
142+ Kinded t1 _t2 -> go (t1 : rest) acc
143+
138144 BinaryNoParensType op l r ->
139145 go (TypeApp (TypeApp op l) r : rest) acc
140146
src/Docs/Search/Types.purs+101−2
@@ -1,5 +1,104 @@
11module Docs.Search.Types where
22
3−type ModuleName = String
3+import Prelude
44
5−type PackageName = String
5+import Data.Argonaut.Decode (class DecodeJson)
6+import Data.Argonaut.Decode.Generic (genericDecodeJson)
7+import Data.Argonaut.Encode (class EncodeJson)
8+import Data.Argonaut.Encode.Generic (genericEncodeJson)
9+import Data.Generic.Rep (class Generic)
10+import Data.Show.Generic (genericShow)
11+import Data.Newtype (class Newtype)
12+
13+
14+newtype Identifier = Identifier String
15+
16+derive instance newtypeIdentifier :: Newtype Identifier _
17+derive instance genericIdentifier :: Generic Identifier _
18+derive newtype instance eqIdentifier :: Eq Identifier
19+derive newtype instance ordIdentifier :: Ord Identifier
20+derive newtype instance showIdentifier :: Show Identifier
21+derive newtype instance decodeJsonIdentifier :: DecodeJson Identifier
22+derive newtype instance encodeJsonIdentifier :: EncodeJson Identifier
23+
24+
25+newtype ModuleName = ModuleName String
26+
27+derive instance newtypeModuleName :: Newtype ModuleName _
28+derive instance genericModuleName :: Generic ModuleName _
29+derive newtype instance eqModuleName :: Eq ModuleName
30+derive newtype instance ordModuleName :: Ord ModuleName
31+derive newtype instance decodeJsonModuleName :: DecodeJson ModuleName
32+derive newtype instance encodeJsonModuleName :: EncodeJson ModuleName
33+
34+instance Show ModuleName where
35+ show = genericShow
36+
37+
38+-- | Non-normalized package name, e.g. `purescript-prelude` or just `prelude`.
39+newtype RawPackageName = RawPackageName String
40+
41+derive instance newtypeRawPackageName :: Newtype RawPackageName _
42+
43+
44+-- | Normalized package name without "purescript-" prefix.
45+newtype PackageName = PackageName String
46+
47+derive instance newtypePackageName :: Newtype PackageName _
48+derive newtype instance eqPackageName :: Eq PackageName
49+derive newtype instance ordPackageName :: Ord PackageName
50+derive newtype instance showPackageName :: Show PackageName
51+derive newtype instance decodeJsonPackageName :: DecodeJson PackageName
52+derive newtype instance encodeJsonPackageName :: EncodeJson PackageName
53+derive instance genericPackageName :: Generic PackageName _
54+
55+
56+data PackageInfo = LocalPackage | Builtin | Package PackageName | UnknownPackage
57+
58+derive instance eqPackageInfo :: Eq PackageInfo
59+derive instance ordPackageInfo :: Ord PackageInfo
60+derive instance genericPackageInfo :: Generic PackageInfo _
61+instance decodeJsonPackageInfo :: DecodeJson PackageInfo where
62+ decodeJson = genericDecodeJson
63+instance encodeJsonPackageInfo :: EncodeJson PackageInfo where
64+ encodeJson = genericEncodeJson
65+
66+instance showPackageInfo :: Show PackageInfo where
67+ show = genericShow
68+
69+
70+newtype PackageScore = PackageScore Int
71+
72+derive instance newtypePackageScore :: Newtype PackageScore _
73+derive instance genericPackageScore :: Generic PackageScore _
74+derive newtype instance eqPackageScore :: Eq PackageScore
75+derive newtype instance ordPackageScore :: Ord PackageScore
76+derive newtype instance semiringPackageScore :: Semiring PackageScore
77+derive newtype instance ringPackageScore :: Ring PackageScore
78+derive newtype instance showPackageScore :: Show PackageScore
79+derive newtype instance decodeJsonPackageScore :: DecodeJson PackageScore
80+derive newtype instance encodeJsonPackageScore :: EncodeJson PackageScore
81+
82+
83+newtype URL = URL String
84+
85+derive instance newtypeURL :: Newtype URL _
86+derive newtype instance showURL :: Show URL
87+
88+newtype FilePath = FilePath String
89+
90+derive instance newtypeFilePath :: Newtype FilePath _
91+derive newtype instance showFilePath :: Show FilePath
92+
93+newtype GlobalIdentifier = GlobalIdentifier String
94+
95+derive instance newtypeGlobalIdentifier :: Newtype GlobalIdentifier _
96+derive newtype instance showGlobalIdentifier :: Show GlobalIdentifier
97+
98+
99+newtype PartId = PartId Int
100+
101+derive instance newtypePartId :: Newtype PartId _
102+derive newtype instance eqPartId :: Eq PartId
103+derive newtype instance ordPartId :: Ord PartId
104+derive newtype instance showPartId :: Show PartId
src/Docs/Search/URIHash.js+1−1
@@ -1,7 +1,7 @@
11/* global exports history */
22
33// https://stackoverflow.com/questions/1397329
4−exports.removeHash = function () {
4+export function removeHash () {
55 var scrollV, scrollH, loc = window.location;
66 if ("pushState" in history)
77 history.pushState("", document.title, loc.pathname + loc.search);
src/Docs/Search/URIHash.purs+3−3
@@ -7,10 +7,10 @@ where
77
88import Prelude
99
10−import Data.Maybe (Maybe(Just), fromMaybe)
10+import Data.Maybe (fromMaybe)
1111import Data.String.CodeUnits as String
1212import Effect (Effect)
13−import Global (decodeURIComponent, encodeURIComponent)
13+import JSURI (decodeURIComponent, encodeURIComponent)
1414import Web.HTML as HTML
1515import Web.HTML.Location as Location
1616import Web.HTML.Window as Window
@@ -31,7 +31,7 @@ getInput = do
3131 location <- Window.location window
3232 hash <- Location.hash location
3333 pure $
34− if String.slice 0 8 hash == Just "#search:"
34+ if String.slice 0 8 hash == "#search:"
3535 then fromMaybe "" $
3636 decodeURIComponent $
3737 String.drop 8 hash
test/Main.purs+14−558
@@ -2,572 +2,28 @@ module Test.Main where
22
33import Prelude
44
5−import Docs.Search.TypeDecoder (Constraint(..), FunDep(..), FunDeps(..), Kind(..), QualifiedName(..), Type(..))
6−import Test.TypeQuery as TypeQuery
7−import Test.IndexBuilder as IndexBuilder
5+import Effect (Effect)
6+import Effect.Aff (launchAff_)
87import Test.Declarations as Declarations
8+import Test.IndexBuilder as IndexBuilder
99import Test.ModuleIndex as ModuleIndex
10−
11−import Test.Extra (assertRight)
12−
13−import Data.Argonaut.Decode (decodeJson)
14−import Data.Argonaut.Encode (encodeJson)
15−import Data.Argonaut.Parser (jsonParser)
16−import Data.Either (fromRight)
17−import Data.Maybe (Maybe(..))
18−import Effect (Effect)
19−import Partial.Unsafe (unsafePartial)
20−import Test.Unit (TestSuite, suite, test)
21−import Test.Unit.Main (runTest)
10+import Test.ModuleParser as ModuleParser
11+import Test.Spec (Spec)
12+import Test.Spec.Reporter.Console (consoleReporter)
13+import Test.Spec.Runner (runSpec)
14+import Test.TypeJson as TypeJson
15+import Test.TypeQuery as TypeQuery
2216
2317main :: Effect Unit
2418main = do
25− runTest mainTest
19+ launchAff_ $ runSpec [consoleReporter] mainTest
20+ -- UI.main
2621
27−mainTest :: TestSuite
22+mainTest :: Spec Unit
2823mainTest = do
24+ ModuleParser.tests
2925 TypeQuery.tests
26+ TypeJson.tests
3027 IndexBuilder.tests
3128 Declarations.tests
3229 ModuleIndex.tests
33−
34− let mkJson x = unsafePartial $ fromRight $ jsonParser x
35− suite "FunDeps decoder" do
36− test "FunDeps" do
37− let funDeps = mkJson """
38− [
39− [
40− [
41− "lhs",
42− "rhs"
43− ],
44− [
45− "output"
46− ]
47− ]
48− ]
49− """
50− assertRight (decodeJson funDeps)
51− (FunDeps [ FunDep { lhs: [ "lhs", "rhs" ]
52− , rhs: [ "output"]
53− }
54− ])
55−
56− suite "Kind decoder" do
57−
58− test "QualifiedName" do
59−
60− let qualifiedName = mkJson """
61− [
62− [
63− "Prim"
64− ],
65− "Type"
66− ]
67− """
68−
69− assertRight (decodeJson qualifiedName)
70− (QualifiedName { moduleName: ["Prim"]
71− , name: "Type"
72− }
73− )
74−
75− test "NamedKind" do
76− let namedKind = mkJson """
77− {
78− "annotation": [],
79− "tag": "NamedKind",
80− "contents": [
81− [
82− "Prim"
83− ],
84− "Type"
85− ]
86− }
87− """
88−
89− assertRight (decodeJson namedKind)
90− (NamedKind $ QualifiedName { moduleName: ["Prim"]
91− , name: "Type"
92− }
93− )
94−
95− test "Row" do
96− let row = mkJson """
97− {
98− "annotation": [],
99− "tag": "Row",
100− "contents": {
101− "annotation": [],
102− "tag": "NamedKind",
103− "contents": [
104− [
105− "Prim"
106− ],
107− "Type"
108− ]
109− }
110− }
111− """
112−
113− assertRight (decodeJson row)
114− (Row $ NamedKind $ QualifiedName { moduleName: ["Prim"]
115− , name: "Type"
116− }
117− )
118−
119− test "FunKind" do
120− let funKind = mkJson """
121− {
122− "annotation": [],
123− "tag": "FunKind",
124− "contents": [
125− {
126− "annotation": [],
127− "tag": "Row",
128− "contents": {
129− "annotation": [],
130− "tag": "NamedKind",
131− "contents": [
132− [
133− "Prim"
134− ],
135− "Type"
136− ]
137− }
138− },
139− {
140− "annotation": [],
141− "tag": "Row",
142− "contents": {
143− "annotation": [],
144− "tag": "NamedKind",
145− "contents": [
146− [
147− "Prim"
148− ],
149− "Type"
150− ]
151− }
152− }
153− ]
154− }
155− """
156− assertRight (decodeJson funKind)
157− (FunKind (Row $ NamedKind $ QualifiedName { moduleName: ["Prim"]
158− , name: "Type"
159− }
160− )
161− (Row $ NamedKind $ QualifiedName { moduleName: ["Prim"]
162− , name: "Type"
163− }
164− )
165− )
166−
167−
168− suite "Constraint decoder" do
169− test "Constraint" do
170− let constraint = mkJson """
171− {
172− "constraintAnn": [],
173− "constraintClass": [
174− [
175− "Prim"
176− ],
177− "Partial"
178− ],
179− "constraintArgs": [],
180− "constraintData": null
181− }
182− """
183− assertRight (decodeJson constraint)
184− (Constraint { constraintClass: QualifiedName { moduleName: ["Prim"]
185− , name: "Partial"
186− }
187− , constraintArgs: []
188− })
189−
190− suite "Type decoder" do
191− test "TypeVar" do
192− let typeVar = mkJson """
193− {
194− "annotation": [],
195− "tag": "TypeVar",
196− "contents": "m"
197− }
198− """
199−
200− assertRight (decodeJson typeVar)
201− (TypeVar "m")
202−
203− test "TypeApp" do
204− let typeApp1 = mkJson """
205− {
206− "annotation": [],
207− "tag": "TypeApp",
208− "contents": [
209− {
210− "annotation": [],
211− "tag": "TypeConstructor",
212− "contents": [
213− [
214− "Control",
215− "Monad",
216− "ST",
217− "Internal"
218− ],
219− "ST"
220− ]
221− },
222− {
223− "annotation": [],
224− "tag": "TypeVar",
225− "contents": "h"
226− }
227− ]
228− }
229− """
230−
231− assertRight (decodeJson typeApp1) $
232− TypeApp
233− (TypeConstructor (QualifiedName { moduleName:
234− [ "Control"
235− , "Monad"
236− , "ST"
237− , "Internal"
238− ],
239− name: "ST"
240− }
241− ))
242− (TypeVar "h")
243−
244− test "TypeOp" do
245− let typeOp = mkJson """
246− {
247− "annotation": [],
248− "tag": "TypeOp",
249− "contents": [
250− [
251− "Data",
252− "NaturalTransformation"
253− ],
254− "~>"
255− ]
256− }
257− """
258− assertRight (decodeJson typeOp) $
259− TypeOp $ QualifiedName { moduleName: [ "Data", "NaturalTransformation" ]
260− , name: "~>"
261− }
262−
263− test "BinaryNoParens" do
264− let binaryNoParens = mkJson """
265− {
266− "annotation": [],
267− "tag": "BinaryNoParensType",
268− "contents": [
269− {
270− "annotation": [],
271− "tag": "TypeOp",
272− "contents": [
273− [
274− "Data",
275− "NaturalTransformation"
276− ],
277− "~>"
278− ]
279− },
280− {
281− "annotation": [],
282− "tag": "TypeVar",
283− "contents": "m"
284− },
285− {
286− "annotation": [],
287− "tag": "TypeVar",
288− "contents": "n"
289− }
290− ]
291− }
292− """
293−
294− assertRight (decodeJson binaryNoParens) $
295− BinaryNoParensType
296− (TypeOp $ QualifiedName { moduleName: ["Data", "NaturalTransformation"], name: "~>" })
297− (TypeVar "m")
298− (TypeVar "n")
299−
300− test "ParensInType" do
301− let parensInType = mkJson """
302− {
303− "annotation": [],
304− "tag": "ParensInType",
305− "contents": {
306− "annotation": [],
307− "tag": "TypeApp",
308− "contents": [
309− {
310− "annotation": [],
311− "tag": "TypeConstructor",
312− "contents": [
313− [
314− "Data",
315− "Maybe"
316− ],
317− "Maybe"
318− ]
319− },
320− {
321− "annotation": [],
322− "tag": "TypeConstructor",
323− "contents": [
324− [
325− "Prim"
326− ],
327− "String"
328− ]
329− }
330− ]
331− }
332− }
333− """
334−
335− assertRight (decodeJson parensInType) $
336− ParensInType $
337− TypeApp
338− (TypeConstructor (QualifiedName { moduleName:
339− [ "Data"
340− , "Maybe"
341− ],
342− name: "Maybe"
343− }
344− ))
345− (TypeConstructor (QualifiedName { moduleName:
346− [ "Prim"
347− ],
348− name: "String"
349− }
350− ))
351− test "RCons" do
352−
353− let rcons = mkJson """
354− {
355− "annotation": [],
356− "tag": "RCons",
357− "contents": [
358− "tail",
359− {
360− "annotation": [],
361− "tag": "TypeApp",
362− "contents": [
363− {
364− "annotation": [],
365− "tag": "TypeConstructor",
366− "contents": [
367− [
368− "Data",
369− "Symbol"
370− ],
371− "SProxy"
372− ]
373− },
374− {
375− "annotation": [],
376− "tag": "TypeVar",
377− "contents": "t"
378− }
379− ]
380− },
381− {
382− "annotation": [],
383− "tag": "REmpty"
384− }
385− ]
386− }
387− """
388−
389− assertRight (decodeJson rcons) $
390− RCons
391− "tail"
392− (TypeApp (TypeConstructor $ QualifiedName { moduleName: [ "Data", "Symbol" ], name: "SProxy" })
393− (TypeVar "t"))
394− REmpty
395−
396− test "ForAll #1" do
397− let forallJson = mkJson """
398− {"annotation":[],"tag":"ForAll","contents":["a",{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"Function"]},{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"String"]}]},{"annotation":[],"tag":"TypeVar","contents":"a"}]},null]}
399− """
400− assertRight (decodeJson forallJson) $
401− ForAll "a" Nothing (TypeApp (TypeApp (TypeConstructor $ qualified ["Prim"] "Function")
402− (TypeConstructor $ qualified ["Prim"] "String"))
403− (TypeVar "a"))
404−
405− test "ForAll #2" do
406− let forallJson = mkJson """
407−{
408− "annotation": [],
409− "tag": "ForAll",
410− "contents": [
411− "f",
412− {
413− "annotation": [],
414− "tag": "FunKind",
415− "contents": [
416− {
417− "annotation": [],
418− "tag": "NamedKind",
419− "contents": [
420− [
421− "Prim",
422− "RowList"
423− ],
424− "RowList"
425− ]
426− },
427− {
428− "annotation": [],
429− "tag": "NamedKind",
430− "contents": [
431− [
432− "Prim"
433− ],
434− "Type"
435− ]
436− }
437− ]
438− },
439− {
440− "annotation": [],
441− "tag": "TypeApp",
442− "contents": [
443− {
444− "annotation": [],
445− "tag": "TypeApp",
446− "contents": [
447− {
448− "annotation": [],
449− "tag": "TypeConstructor",
450− "contents": [
451− [
452− "Prim"
453− ],
454− "Function"
455− ]
456− },
457− {
458− "annotation": [],
459− "tag": "TypeApp",
460− "contents": [
461− {
462− "annotation": [],
463− "tag": "TypeVar",
464− "contents": "f"
465− },
466− {
467− "annotation": [],
468− "tag": "TypeVar",
469− "contents": "l"
470− }
471− ]
472− }
473− ]
474− },
475− {
476− "annotation": [],
477− "tag": "TypeApp",
478− "contents": [
479− {
480− "annotation": [],
481− "tag": "TypeConstructor",
482− "contents": [
483− [
484− "Data",
485− "List",
486− "Types"
487− ],
488− "List"
489− ]
490− },
491− {
492− "annotation": [],
493− "tag": "ParensInType",
494− "contents": {
495− "annotation": [],
496− "tag": "TypeApp",
497− "contents": [
498− {
499− "annotation": [],
500− "tag": "TypeApp",
501− "contents": [
502− {
503− "annotation": [],
504− "tag": "TypeConstructor",
505− "contents": [
506− [
507− "Data",
508− "Tuple"
509− ],
510− "Tuple"
511− ]
512− },
513− {
514− "annotation": [],
515− "tag": "TypeConstructor",
516− "contents": [
517− [
518− "Prim"
519− ],
520− "String"
521− ]
522− }
523− ]
524− },
525− {
526− "annotation": [],
527− "tag": "TypeConstructor",
528− "contents": [
529− [
530− "Prim"
531− ],
532− "String"
533− ]
534− }
535− ]
536− }
537− }
538− ]
539− }
540− ]
541− },
542− null
543− ]
544−}
545− """
546− assertRight (decodeJson forallJson) $
547− ForAll "f"
548− (Just (FunKind (NamedKind (QualifiedName { moduleName: ["Prim","RowList"], name: "RowList" })) (NamedKind (QualifiedName { moduleName: ["Prim"], name: "Type" }))))
549− (TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Prim"], name: "Function" })) (TypeApp (TypeVar "f") (TypeVar "l"))) (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Data","List","Types"], name: "List" })) (ParensInType (TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Data","Tuple"], name: "Tuple" })) (TypeConstructor (QualifiedName { moduleName: ["Prim"], name: "String" }))) (TypeConstructor (QualifiedName { moduleName: ["Prim"], name: "String" }))))))
550−
551−
552−
553−
554− suite "jsons" do
555−
556− test "jsons #1" do
557− let json = mkJson """
558−{"annotation":[],"tag":"ForAll","contents":["o",{"annotation":[],"tag":"ForAll","contents":["r",{"annotation":[],"tag":"ForAll","contents":["l",{"annotation":[],"tag":"ConstrainedType","contents":[{"constraintAnn":[],"constraintClass":[["Type","Data","Boolean"],"And"],"constraintArgs":[{"annotation":[],"tag":"TypeVar","contents":"l"},{"annotation":[],"tag":"TypeVar","contents":"r"},{"annotation":[],"tag":"TypeVar","contents":"o"}],"constraintData":null},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"Function"]},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Type","Data","Boolean"],"BProxy"]},{"annotation":[],"tag":"TypeVar","contents":"l"}]}]},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"Function"]},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Type","Data","Boolean"],"BProxy"]},{"annotation":[],"tag":"TypeVar","contents":"r"}]}]},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Type","Data","Boolean"],"BProxy"]},{"annotation":[],"tag":"TypeVar","contents":"o"}]}]}]}]},null]},null]},null]}
559− """
560−
561− assertRight (decodeJson json) $ (ForAll "o" Nothing (ForAll "r" Nothing (ForAll "l" Nothing (ConstrainedType (Constraint { constraintArgs: [(TypeVar "l"),(TypeVar "r"),(TypeVar "o")], constraintClass: (QualifiedName { moduleName: ["Type","Data","Boolean"], name: "And" }) }) (TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Prim"], name: "Function" })) (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Type","Data","Boolean"], name: "BProxy" })) (TypeVar "l"))) (TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Prim"], name: "Function" })) (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Type","Data","Boolean"], name: "BProxy" })) (TypeVar "r"))) (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Type","Data","Boolean"], name: "BProxy" })) (TypeVar "o"))))))))
562−
563− suite "Kind encoder" do
564− test "FunKind" do
565− let k1 =
566− FunKind (Row (NamedKind $ qualified [] "a"))
567− (FunKind (NamedKind $ qualified [] "b")
568− (NamedKind $ qualified [] "b"))
569− assertRight (decodeJson $ encodeJson $ k1) k1
570−
571−
572−qualified :: Array String -> String -> QualifiedName
573−qualified moduleName name = QualifiedName { moduleName, name }
test/Test/Declarations.purs+18−16
@@ -2,36 +2,38 @@ module Test.Declarations where
22
33import Prelude
44
5−import Data.Maybe (Maybe(..))
65import Docs.Search.Declarations (extractPackageName)
6+import Docs.Search.Types (PackageName(..), PackageInfo(..))
77
8−import Test.Unit (TestSuite, suite, test)
9−import Test.Unit.Assert as Assert
8+import Data.Maybe (Maybe(..))
9+import Data.Newtype (wrap)
10+import Test.Spec (Spec, describe, it)
11+import Test.Spec.Assertions (shouldEqual)
1012
11−tests :: TestSuite
13+tests :: Spec Unit
1214tests = do
13− suite "Declarations" do
14− test "extractPackageName" do
15− Assert.equal "<builtin>" (extractPackageName "Prim" Nothing)
16− Assert.equal "<builtin>" (extractPackageName "Prim.Foo" Nothing)
17− Assert.equal "<builtin>" (extractPackageName "Prim.Foo.Bar" Nothing)
18− Assert.equal "<unknown>" (extractPackageName "Primitive" Nothing)
19− Assert.equal "foo"
20− (extractPackageName "Foo" $
15+ describe "Declarations" do
16+ it "extractPackageName works correctly" do
17+ Builtin `shouldEqual` (extractPackageName (wrap "Prim") Nothing)
18+ Builtin `shouldEqual` (extractPackageName (wrap "Prim.Foo") Nothing)
19+ Builtin `shouldEqual` (extractPackageName (wrap "Prim.Foo.Bar") Nothing)
20+ UnknownPackage `shouldEqual` (extractPackageName (wrap "Primitive") Nothing)
21+ Package (PackageName "foo") `shouldEqual`
22+ (extractPackageName (wrap "Foo") $
2123 Just { start: []
2224 , end: []
2325 , name: ".spago/foo/src/Foo.purs"
2426 }
2527 )
26− Assert.equal "bar"
27− (extractPackageName "Bar" $
28+ Package (PackageName "bar") `shouldEqual`
29+ (extractPackageName (wrap "Bar") $
2830 Just { start: []
2931 , end: []
3032 , name: "/path/to/somewhere/bower_components/bar/src/Bar.purs"
3133 }
3234 )
33− Assert.equal "<local package>"
34− (extractPackageName "Bar" $
35+ LocalPackage `shouldEqual`
36+ (extractPackageName (wrap "Bar") $
3537 Just { start: []
3638 , end: []
3739 , name: "/path/to/somewhere/src/Bar.purs"
test/Test/Extra.purs+6−5
@@ -4,7 +4,8 @@ import Prelude
44
55import Data.Either (Either(..))
66import Effect.Aff (Aff)
7−import Test.Unit.Assert as Assert
7+import Test.Spec.Assertions (shouldEqual)
8+
89
910assertRight
1011 :: forall a b
@@ -17,7 +18,7 @@ assertRight
1718 -> Aff Unit
1819assertRight eiActual expected =
1920 case eiActual of
20− Left string -> do
21− Assert.equal (Right expected) eiActual
22− Right actual -> do
23− Assert.equal (Right expected) eiActual
21+ Left _ -> do
22+ Right expected `shouldEqual` eiActual
23+ Right _ -> do
24+ Right expected `shouldEqual` eiActual
test/Test/IndexBuilder.purs+9−9
@@ -5,16 +5,16 @@ import Prelude
55import Docs.Search.IndexBuilder (patchHTML)
66
77import Data.Tuple (snd)
8−import Test.Unit (TestSuite, suite, test)
9−import Test.Unit.Assert as Assert
8+import Test.Spec (Spec, describe, it)
9+import Test.Spec.Assertions (shouldEqual, shouldNotSatisfy)
1010
11−tests :: TestSuite
11+tests :: Spec Unit
1212tests = do
13− suite "IndexBuilder" do
14− suite "patchHTML" do
15− test "works" do
13+ describe "IndexBuilder" do
14+ describe "patchHTML" do
15+ it "works" do
1616 let input = "</body>"
17− Assert.assertFalse "patchHTML works" (snd (patchHTML input) == input)
18− test "is idempotent" do
17+ shouldNotSatisfy (snd (patchHTML input)) (eq input)
18+ it "is idempotent" do
1919 let input = "</body>"
20− Assert.equal (snd $ patchHTML $ snd $ patchHTML input) (snd $ patchHTML input)
20+ shouldEqual (snd $ patchHTML $ snd $ patchHTML input) (snd $ patchHTML input)
test/Test/ModuleIndex.purs+9−10
@@ -5,20 +5,19 @@ import Docs.Search.ModuleIndex (extractModuleNameParts)
55import Prelude
66
77import Data.List as List
8−import Test.Unit (TestSuite, suite, test)
9−import Test.Unit.Assert as Assert
8+import Data.Newtype (wrap)
9+import Test.Spec (Spec, describe, it)
10+import Test.Spec.Assertions (shouldEqual)
1011
1112
12−tests :: TestSuite
13+tests :: Spec Unit
1314tests = do
14− suite "ModuleIndex" do
15+ describe "ModuleIndex" do
1516
16− test "test #0" do
17− Assert.equal (extractModuleNameParts "Data.Array.ST") (
17+ it "test #0" do
18+ extractModuleNameParts (wrap "Data.Array.ST") `shouldEqual`
1819 List.fromFoldable [ "st", "array.st", "data.array.st" ]
19− )
2020
21− test "test #1" do
22− Assert.equal (extractModuleNameParts "Foo") (
21+ it "test #1" do
22+ extractModuleNameParts (wrap "Foo") `shouldEqual`
2323 List.fromFoldable [ "foo" ]
24− )
test/Test/ModuleParser.pursnew file+61
@@ -0,0 +1,61 @@
1+module Test.ModuleParser where
2+
3+import Docs.Search.IndexBuilder (getPathsByGlobs)
4+import Docs.Search.ModuleParser (multiLineComment, parseModuleName, singleLineComment)
5+import Docs.Search.Types (ModuleName(..))
6+
7+import Prelude
8+
9+import Data.Array as Array
10+import Data.Either (Either(..))
11+import Data.Foldable (for_)
12+import Data.Maybe (Maybe(..))
13+import Effect.Class (liftEffect)
14+import Effect.Console as Console
15+import Effect.Exception (throw)
16+import Node.Encoding (Encoding(..))
17+import Node.FS.Aff (readTextFile)
18+import StringParser (runParser)
19+import Test.Spec (Spec, describe, it)
20+import Test.Spec.Assertions (shouldEqual)
21+
22+tests :: Spec Unit
23+tests = do
24+ describe "ModuleParser" do
25+ it "test #0" do
26+ parseModuleName "module Foo" `shouldEqual` Just (ModuleName "Foo")
27+ it "test #1" do
28+ parseModuleName "module Foo.Bar.B" `shouldEqual` Just (ModuleName "Foo.Bar.B")
29+ it "test #2" do
30+ parseModuleName " module Foo" `shouldEqual` Just (ModuleName "Foo")
31+ it "test #3" do
32+ parseModuleName " {- asdas -} module Foo" `shouldEqual` Just (ModuleName "Foo")
33+ it "test #4" do
34+ parseModuleName "{--}module Foo" `shouldEqual` Just (ModuleName "Foo")
35+ it "test #5" do
36+ parseModuleName "--\nmodule Foo" `shouldEqual` Just (ModuleName "Foo")
37+ it "test #6" do
38+ parseModuleName "--\n-- foo\nmodule Foo" `shouldEqual` Just (ModuleName "Foo")
39+ it "test #7" do
40+ parseModuleName "-- \n -- foo\n {- bar -} --baz\n module Foo" `shouldEqual` Just (ModuleName "Foo")
41+ it "multiline comment #1" do
42+ runParser multiLineComment "{--}" `shouldEqual` Right unit
43+ it "multiline comment #1" do
44+ runParser multiLineComment "{- foo -}" `shouldEqual` Right unit
45+ it "multiline comment #1" do
46+ runParser multiLineComment "{- foo\nbar\nbar\n -}" `shouldEqual` Right unit
47+ it "single line comment #1" do
48+ runParser singleLineComment "-- asd\n" `shouldEqual` Right unit
49+ it "single line comment #1" do
50+ runParser singleLineComment "--\n" `shouldEqual` Right unit
51+ it "Parses every module in .spago/" do
52+ files <- getPathsByGlobs ["./.spago/**/*.purs"]
53+ liftEffect $ Console.log $ "Modules in .spago: " <> show (Array.length files)
54+ for_ files \filePath -> do
55+ fileContents <- readTextFile UTF8 filePath
56+ case parseModuleName fileContents of
57+ Nothing -> do
58+ liftEffect $ throw $
59+ "Module header decoding failed for " <> filePath <>
60+ ", unable to extract module name"
61+ Just _ -> pure unit
test/Test/TypeJson.pursnew file+300
@@ -0,0 +1,300 @@
1+module Test.TypeJson
2+ ( tests )
3+where
4+
5+import Prelude
6+
7+import Docs.Search.TypeDecoder (Constraint(..), FunDep(..), FunDeps(..), QualifiedName(..), Type(..))
8+import Docs.Search.Types (Identifier(..))
9+import Test.Extra (assertRight)
10+import Test.TypeQuery as TypeQuery
11+
12+import Data.Argonaut.Core (Json)
13+import Data.Argonaut.Decode (decodeJson)
14+import Data.Argonaut.Parser (jsonParser)
15+import Data.Either (Either(..))
16+import Data.Maybe (Maybe(..))
17+import Partial.Unsafe (unsafePartial)
18+import Test.Spec (Spec, describe, it)
19+
20+
21+tests :: Spec Unit
22+tests = do
23+ describe "FunDeps decoder" do
24+ it "FunDeps" do
25+ let
26+ funDeps = mkJson """
27+ [
28+ [
29+ [
30+ "lhs",
31+ "rhs"
32+ ],
33+ [
34+ "output"
35+ ]
36+ ]
37+ ]
38+ """
39+ assertRight (decodeJson funDeps)
40+ (FunDeps [ FunDep { lhs: [ "lhs", "rhs" ]
41+ , rhs: [ "output"]
42+ }
43+ ])
44+
45+ describe "Constraint decoder" do
46+ it "Constraint" do
47+ let constraint = mkJson """
48+ {
49+ "constraintAnn": [],
50+ "constraintClass": [
51+ [
52+ "Prim"
53+ ],
54+ "Partial"
55+ ],
56+ "constraintArgs": [],
57+ "constraintData": null
58+ }
59+ """
60+ assertRight (decodeJson constraint)
61+ (Constraint { constraintClass: qualified ["Prim"] "Partial"
62+ , constraintArgs: []
63+ })
64+
65+ describe "Type decoder" do
66+ it "TypeVar" do
67+ let typeVar = mkJson """
68+ {
69+ "annotation": [],
70+ "tag": "TypeVar",
71+ "contents": "m"
72+ }
73+ """
74+
75+ assertRight (decodeJson typeVar)
76+ (TypeVar "m")
77+
78+ it "TypeApp" do
79+ let typeApp1 = mkJson """
80+ {
81+ "annotation": [],
82+ "tag": "TypeApp",
83+ "contents": [
84+ {
85+ "annotation": [],
86+ "tag": "TypeConstructor",
87+ "contents": [
88+ [
89+ "Control",
90+ "Monad",
91+ "ST",
92+ "Internal"
93+ ],
94+ "ST"
95+ ]
96+ },
97+ {
98+ "annotation": [],
99+ "tag": "TypeVar",
100+ "contents": "h"
101+ }
102+ ]
103+ }
104+ """
105+
106+ assertRight (decodeJson typeApp1) $
107+ TypeApp
108+ (TypeConstructor (qualified [ "Control"
109+ , "Monad"
110+ , "ST"
111+ , "Internal"
112+ ]
113+ "ST"
114+ ))
115+ (TypeVar "h")
116+
117+ it "TypeOp" do
118+ let typeOp = mkJson """
119+ {
120+ "annotation": [],
121+ "tag": "TypeOp",
122+ "contents": [
123+ [
124+ "Data",
125+ "NaturalTransformation"
126+ ],
127+ "~>"
128+ ]
129+ }
130+ """
131+ assertRight (decodeJson typeOp) $
132+ TypeOp $ qualified [ "Data", "NaturalTransformation" ] "~>"
133+
134+ it "BinaryNoParens" do
135+ let binaryNoParens = mkJson """
136+ {
137+ "annotation": [],
138+ "tag": "BinaryNoParensType",
139+ "contents": [
140+ {
141+ "annotation": [],
142+ "tag": "TypeOp",
143+ "contents": [
144+ [
145+ "Data",
146+ "NaturalTransformation"
147+ ],
148+ "~>"
149+ ]
150+ },
151+ {
152+ "annotation": [],
153+ "tag": "TypeVar",
154+ "contents": "m"
155+ },
156+ {
157+ "annotation": [],
158+ "tag": "TypeVar",
159+ "contents": "n"
160+ }
161+ ]
162+ }
163+ """
164+
165+ assertRight (decodeJson binaryNoParens) $
166+ BinaryNoParensType
167+ (TypeOp $ qualified ["Data", "NaturalTransformation"] "~>")
168+ (TypeVar "m")
169+ (TypeVar "n")
170+
171+ it "ParensInType" do
172+ let parensInType = mkJson """
173+ {
174+ "annotation": [],
175+ "tag": "ParensInType",
176+ "contents": {
177+ "annotation": [],
178+ "tag": "TypeApp",
179+ "contents": [
180+ {
181+ "annotation": [],
182+ "tag": "TypeConstructor",
183+ "contents": [
184+ [
185+ "Data",
186+ "Maybe"
187+ ],
188+ "Maybe"
189+ ]
190+ },
191+ {
192+ "annotation": [],
193+ "tag": "TypeConstructor",
194+ "contents": [
195+ [
196+ "Prim"
197+ ],
198+ "String"
199+ ]
200+ }
201+ ]
202+ }
203+ }
204+ """
205+
206+ assertRight (decodeJson parensInType) $
207+ ParensInType $
208+ TypeApp
209+ (TypeConstructor (qualified [ "Data", "Maybe" ] "Maybe"))
210+ (TypeConstructor (qualified [ "Prim" ] "String"))
211+ it "RCons" do
212+
213+ let rcons = mkJson """
214+ {
215+ "annotation": [],
216+ "tag": "RCons",
217+ "contents": [
218+ "tail",
219+ {
220+ "annotation": [],
221+ "tag": "TypeApp",
222+ "contents": [
223+ {
224+ "annotation": [],
225+ "tag": "TypeConstructor",
226+ "contents": [
227+ [
228+ "Data",
229+ "Symbol"
230+ ],
231+ "SProxy"
232+ ]
233+ },
234+ {
235+ "annotation": [],
236+ "tag": "TypeVar",
237+ "contents": "t"
238+ }
239+ ]
240+ },
241+ {
242+ "annotation": [],
243+ "tag": "REmpty"
244+ }
245+ ]
246+ }
247+ """
248+
249+ assertRight (decodeJson rcons) $
250+ RCons
251+ (Identifier "tail")
252+ (TypeApp (TypeConstructor $ qualified [ "Data", "Symbol" ] "SProxy")
253+ (TypeVar "t"))
254+ REmpty
255+
256+ it "ForAll #1" do
257+ let forallJson = mkJson """
258+ {"annotation":[],"tag":"ForAll","contents":["a",{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"Function"]},{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"String"]}]},{"annotation":[],"tag":"TypeVar","contents":"a"}]},null]}
259+ """
260+ assertRight (decodeJson forallJson) $
261+ ForAll "a" Nothing (TypeApp (TypeApp (TypeConstructor $ qualified ["Prim"] "Function")
262+ (TypeConstructor $ qualified ["Prim"] "String"))
263+ (TypeVar "a"))
264+
265+ it "KindApp" do
266+ let kindAppJson = mkJson """
267+ {"annotation":[],"tag":"KindApp","contents":[{"annotation":[],"tag":"REmpty"},{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"Type"]}]}
268+ """
269+ assertRight (decodeJson kindAppJson) $
270+ KindApp REmpty (TypeConstructor (qualified ["Prim"] "Type"))
271+ it "KindedType" do
272+ let kindedTypeJson = mkJson """
273+ {"annotation":[],"tag":"KindedType","contents":[{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Data","Const"],"Const"]},{"annotation":[],"tag":"TypeConstructor","contents":[["Data","Void"],"Void"]}]},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"Function"]},{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"Type"]}]},{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"Type"]}]}]}
274+ """
275+ assertRight (decodeJson kindedTypeJson) $
276+ Kinded
277+ (TypeApp
278+ (TypeConstructor (qualified ["Data","Const"] "Const"))
279+ (TypeConstructor (qualified ["Data","Void"] "Void")))
280+ (TypeApp (TypeApp
281+ (TypeConstructor (qualified ["Prim"] "Function"))
282+ (TypeConstructor (qualified ["Prim"] "Type" )))
283+ (TypeConstructor (qualified ["Prim"] "Type")))
284+ describe "jsons" do
285+
286+ it "jsons #1" do
287+ let json = mkJson """
288+{"annotation":[],"tag":"ForAll","contents":["o",{"annotation":[],"tag":"ForAll","contents":["r",{"annotation":[],"tag":"ForAll","contents":["l",{"annotation":[],"tag":"ConstrainedType","contents":[{"constraintAnn":[],"constraintClass":[["Type","Data","Boolean"],"And"],"constraintArgs":[{"annotation":[],"tag":"TypeVar","contents":"l"},{"annotation":[],"tag":"TypeVar","contents":"r"},{"annotation":[],"tag":"TypeVar","contents":"o"}],"constraintData":null},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"Function"]},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Type","Data","Boolean"],"BProxy"]},{"annotation":[],"tag":"TypeVar","contents":"l"}]}]},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Prim"],"Function"]},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Type","Data","Boolean"],"BProxy"]},{"annotation":[],"tag":"TypeVar","contents":"r"}]}]},{"annotation":[],"tag":"TypeApp","contents":[{"annotation":[],"tag":"TypeConstructor","contents":[["Type","Data","Boolean"],"BProxy"]},{"annotation":[],"tag":"TypeVar","contents":"o"}]}]}]}]},null]},null]},null]}
289+ """
290+
291+ assertRight (decodeJson json) $ (ForAll "o" Nothing (ForAll "r" Nothing (ForAll "l" Nothing (ConstrainedType (Constraint { constraintArgs: [(TypeVar "l"),(TypeVar "r"),(TypeVar "o")], constraintClass: (QualifiedName { moduleNameParts: ["Type","Data","Boolean"], name: Identifier "And" }) }) (TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleNameParts: ["Prim"], name: Identifier "Function" })) (TypeApp (TypeConstructor (QualifiedName { moduleNameParts: ["Type","Data","Boolean"], name: Identifier "BProxy" })) (TypeVar "l"))) (TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleNameParts: ["Prim"], name: Identifier "Function" })) (TypeApp (TypeConstructor (QualifiedName { moduleNameParts: ["Type","Data","Boolean"], name: Identifier "BProxy" })) (TypeVar "r"))) (TypeApp (TypeConstructor (QualifiedName { moduleNameParts: ["Type","Data","Boolean"], name: Identifier "BProxy" })) (TypeVar "o"))))))))
292+
293+
294+qualified :: Array String -> String -> QualifiedName
295+qualified = TypeQuery.qname
296+
297+mkJson :: String -> Json
298+mkJson str =
299+ unsafePartial $ case jsonParser str of
300+ Right r -> r
test/Test/TypeQuery.purs+425−250
@@ -3,9 +3,10 @@ module Test.TypeQuery where
33import Docs.Search.TypeDecoder (Constraint(..), QualifiedName(..), Type(..))
44import Docs.Search.TypeQuery (Substitution(..), TypeQuery(..), getFreeVariables, parseTypeQuery, penalty, typeVarPenalty)
55import Docs.Search.TypeShape (ShapeChunk(..), shapeOfType, shapeOfTypeQuery)
6+import Docs.Search.Types (Identifier(..))
67
78import Prelude
8−
9+import Prim hiding (Constraint, Type)
910import Data.Foldable (class Foldable)
1011import Data.List (List(..), (:))
1112import Data.List as List
@@ -14,392 +15,566 @@ import Data.List.NonEmpty as NonEmptyList
1415import Data.Set as Set
1516import Data.Tuple (Tuple(..))
1617import Test.Extra (assertRight)
17−import Test.Unit (TestSuite, suite, test)
18−import Test.Unit.Assert as Assert
18+import Test.Spec (Spec, describe, it)
19+import Test.Spec.Assertions (shouldEqual, shouldSatisfy)
1920import Data.Maybe (Maybe(..))
2021
21−
22−tests :: TestSuite
22+tests :: Spec Unit
2323tests = do
24− suite "TypeQuery parser" do
24+ describe "TypeQuery parser" do
2525
26− test "test #0" do
26+ it "test #0" do
2727 let input = "a"
28− assertRight (parseTypeQuery input) (QVar "a")
28+ assertRight (parseTypeQuery input) (qVar "a")
2929
30− test "test #1" do
30+ it "test #1" do
3131 let input = "ab"
32− assertRight (parseTypeQuery input) (QVar "ab")
32+ assertRight (parseTypeQuery input) (qVar "ab")
3333
34− test "test #2" do
34+ it "test #2" do
3535 let input = "a b"
36− assertRight (parseTypeQuery input) (QApp (QVar "a") (QVar "b"))
36+ assertRight (parseTypeQuery input) (QApp (qVar "a") (qVar "b"))
3737
38− test "test #3" do
38+ it "test #3" do
3939 let input = "a b c"
40− assertRight (parseTypeQuery input) (QApp (QApp (QVar "a") (QVar "b")) (QVar "c"))
40+ assertRight (parseTypeQuery input) (QApp (QApp (qVar "a") (qVar "b")) (qVar "c"))
4141
42− test "test #4" do
42+ it "test #4" do
4343 let input = "a -> b"
44− assertRight (parseTypeQuery input) (QFun (QVar "a") (QVar "b"))
44+ assertRight (parseTypeQuery input) (QFun (qVar "a") (qVar "b"))
4545
46− test "test #5" do
46+ it "test #5" do
4747 let input = "a -> b c"
48− assertRight (parseTypeQuery input) (QFun (QVar "a") (QApp (QVar "b") (QVar "c")))
48+ assertRight (parseTypeQuery input) (QFun (qVar "a") (QApp (qVar "b") (qVar "c")))
4949
50− test "test #6" do
50+ it "test #6" do
5151 let input = "a b -> c"
52− assertRight (parseTypeQuery input) (QFun (QApp (QVar "a") (QVar "b")) (QVar "c"))
52+ assertRight (parseTypeQuery input) (QFun (QApp (qVar "a") (qVar "b")) (qVar "c"))
5353
54− test "test #7" do
54+ it "test #7" do
5555 let input = "a b"
56− assertRight (parseTypeQuery input) (QApp (QVar "a") (QVar "b"))
56+ assertRight (parseTypeQuery input) (QApp (qVar "a") (qVar "b"))
5757
58− test "test #8" do
58+ it "test #8" do
5959 let input = "a (b c)"
60− assertRight (parseTypeQuery input) (QApp (QVar "a") (QApp (QVar "b") (QVar "c")))
60+ assertRight (parseTypeQuery input) (QApp (qVar "a") (QApp (qVar "b") (qVar "c")))
6161
62− test "test #9" do
62+ it "test #9" do
6363 let input = "(a b) (c d)"
6464 assertRight (parseTypeQuery input)
65− (QApp (QApp (QVar "a") (QVar "b"))
66− (QApp (QVar "c") (QVar "d")))
65+ ( QApp (QApp (qVar "a") (qVar "b"))
66+ (QApp (qVar "c") (qVar "d"))
67+ )
6768
68− test "test #10" do
69+ it "test #10" do
6970 let input = "a ( b c )"
70− assertRight (parseTypeQuery input) (QApp (QVar "a") (QApp (QVar "b") (QVar "c")))
71+ assertRight (parseTypeQuery input) (QApp (qVar "a") (QApp (qVar "b") (qVar "c")))
7172
72− test "test #11" do
73+ it "test #11" do
7374 let input = "aaa"
74− assertRight (parseTypeQuery input) (QVar "aaa")
75+ assertRight (parseTypeQuery input) (qVar "aaa")
7576
76− test "test #12" do
77+ it "test #12" do
7778 let input = "aaa ( bbb ccc )"
78− assertRight (parseTypeQuery input) (QApp (QVar "aaa") (QApp (QVar "bbb") (QVar "ccc")))
79+ assertRight (parseTypeQuery input) (QApp (qVar "aaa") (QApp (qVar "bbb") (qVar "ccc")))
7980
80− test "test #13" do
81+ it "test #13" do
8182 let input = "(a -> b) -> (c -> d)"
82− assertRight (parseTypeQuery input) (QFun (QFun (QVar "a") (QVar "b"))
83− (QFun (QVar "c") (QVar "d")))
83+ assertRight (parseTypeQuery input)
84+ ( QFun (QFun (qVar "a") (qVar "b"))
85+ (QFun (qVar "c") (qVar "d"))
86+ )
8487
85− test "test #14" do
88+ it "test #14" do
8689 let input = "a -> b -> c -> d"
87− assertRight (parseTypeQuery input) (QFun (QVar "a")
88− (QFun (QVar "b")
89− (QFun (QVar "c") (QVar "d"))))
90+ assertRight (parseTypeQuery input)
91+ ( QFun (qVar "a")
92+ ( QFun (qVar "b")
93+ (QFun (qVar "c") (qVar "d"))
94+ )
95+ )
9096
91− test "test #15" do
97+ it "test #15" do
9298 let input = "a -> b -> c"
93− assertRight (parseTypeQuery input) (QFun (QVar "a")
94− (QFun (QVar "b")
95− (QVar "c")))
99+ assertRight (parseTypeQuery input)
100+ ( QFun (qVar "a")
101+ ( QFun (qVar "b")
102+ (qVar "c")
103+ )
104+ )
96105
97− test "test #16" do
106+ it "test #16" do
98107 let input = "forall a b c. c"
99− assertRight (parseTypeQuery input) (QForAll (nl "a" ["b", "c"]) (QVar "c"))
108+ assertRight (parseTypeQuery input) (QForAll (nl "a" [ "b", "c" ]) (qVar "c"))
100109
101− test "test #17" do
110+ it "test #17" do
102111 let input = "forall a. Maybe a"
103− assertRight (parseTypeQuery input) (QForAll (nl "a" $ []) (QApp (QConst "Maybe") (QVar "a")))
112+ assertRight (parseTypeQuery input) (QForAll (nl "a" $ []) (QApp (qConst "Maybe") (qVar "a")))
104113
105− test "test #18" do
114+ it "test #18" do
106115 let input = "forall m a. Monad m => a -> m a"
107116 assertRight (parseTypeQuery input)
108− (QForAll (nl "m" ["a"])
109− (QConstraint "Monad" (l [QVar "m"])
110− (QFun (QVar "a")
111− (QApp (QVar "m") (QVar "a")))))
112−
113− test "test #19" do
117+ ( QForAll (nl "m" [ "a" ])
118+ ( qConstraint "Monad" (l [ qVar "m" ])
119+ ( QFun (qVar "a")
120+ (QApp (qVar "m") (qVar "a"))
121+ )
122+ )
123+ )
124+
125+ it "test #19" do
114126 let input = "{ a :: Int }"
115127 assertRight (parseTypeQuery input)
116− (QApp (QConst "Record") (QRow (pure (Tuple "a" (QConst "Int")))))
128+ (QApp (qConst "Record") (QRow (pure (Tuple (Identifier "a") (qConst "Int")))))
117129
118− test "test #20" do
130+ it "test #20" do
119131 let input = "{a::Int}"
120132 assertRight (parseTypeQuery input)
121− (QApp (QConst "Record") (QRow (pure (Tuple "a" (QConst "Int")))))
133+ (QApp (qConst "Record") (QRow (pure (Tuple (Identifier "a") (qConst "Int")))))
122134
123− test "test #21" do
135+ it "test #21" do
124136 let input = "Int"
125− assertRight (parseTypeQuery input) (QConst "Int")
137+ assertRight (parseTypeQuery input) (qConst "Int")
126138
127− test "test #22" do
139+ it "test #22" do
128140 let input = "a->b"
129− assertRight (parseTypeQuery input) (QFun (QVar "a") (QVar "b"))
141+ assertRight (parseTypeQuery input) (QFun (qVar "a") (qVar "b"))
130142
131− test "test #23" do
143+ it "test #23" do
132144 let input = "forall m a. MonadRec m => Process m a -> m a"
133− assertRight (parseTypeQuery input) (QForAll (nl "m" ("a" : Nil))
134− (QConstraint "MonadRec" (l [QVar "m"])
135− (QFun (QApp (QApp (QConst "Process")
136− (QVar "m")) (QVar "a"))
137− (QApp (QVar "m") (QVar "a")))))
138−
139− test "test #24" do
145+ assertRight (parseTypeQuery input)
146+ ( QForAll (nl "m" ("a" : Nil))
147+ ( qConstraint "MonadRec" (l [ qVar "m" ])
148+ ( QFun
149+ ( QApp
150+ ( QApp (qConst "Process")
151+ (qVar "m")
152+ )
153+ (qVar "a")
154+ )
155+ (QApp (qVar "m") (qVar "a"))
156+ )
157+ )
158+ )
159+
160+ it "test #24" do
140161 let input = "forall t f a. Foldable1 t => Apply f => f"
141− assertRight (parseTypeQuery input) (QForAll (nl "t" ["f", "a"])
142− (QConstraint "Foldable1" (l [QVar "t"])
143− (QConstraint "Apply" (l [QVar "f"]) (QVar "f"))))
162+ assertRight (parseTypeQuery input)
163+ ( QForAll (nl "t" [ "f", "a" ])
164+ ( qConstraint "Foldable1" (l [ qVar "t" ])
165+ (qConstraint "Apply" (l [ qVar "f" ]) (qVar "f"))
166+ )
167+ )
144168
145− test "test #25" do
169+ it "test #25" do
146170 let input = "forall m a.MonadRec m=>Process m a->m a"
147− assertRight (parseTypeQuery input) ((QForAll (nl "m" ("a" : Nil))
148− (QConstraint "MonadRec" (l [QVar "m"])
149− (QFun (QApp (QApp (QConst "Process")
150− (QVar "m")) (QVar "a"))
151− (QApp (QVar "m") (QVar "a"))))))
152−
153− test "test #26" do
171+ assertRight (parseTypeQuery input)
172+ ( ( QForAll (nl "m" ("a" : Nil))
173+ ( qConstraint "MonadRec" (l [ qVar "m" ])
174+ ( QFun
175+ ( QApp
176+ ( QApp (qConst "Process")
177+ (qVar "m")
178+ )
179+ (qVar "a")
180+ )
181+ (QApp (qVar "m") (qVar "a"))
182+ )
183+ )
184+ )
185+ )
186+
187+ it "test #26" do
154188 let input = "m a -> (a -> m b) -> m b"
155− assertRight (parseTypeQuery input) (QFun (QApp (QVar "m") (QVar "a")) (QFun (QFun (QVar "a") (QApp (QVar "m") (QVar "b"))) (QApp (QVar "m") (QVar "b"))))
189+ assertRight (parseTypeQuery input) (QFun (QApp (qVar "m") (qVar "a")) (QFun (QFun (qVar "a") (QApp (qVar "m") (qVar "b"))) (QApp (qVar "m") (qVar "b"))))
156190
157− test "test #27" do
191+ it "test #27" do
158192 let input = "forall f a. Alternative f => Lazy (f (List a)) => f a -> f (List a)"
159− assertRight (parseTypeQuery input) ((QForAll (nl "f" ["a"]))
160− (QConstraint "Alternative" (l [QVar "f"])
161− (QConstraint "Lazy" (l [QApp (QVar "f")
162− (QApp (QConst "List") (QVar "a"))])
163− (QFun (QApp (QVar "f") (QVar "a"))
164− (QApp (QVar "f")
165− (QApp (QConst "List") (QVar "a")))))))
166−
167− test "test #28" do
193+ assertRight (parseTypeQuery input)
194+ ( (QForAll (nl "f" [ "a" ]))
195+ ( qConstraint "Alternative" (l [ qVar "f" ])
196+ ( qConstraint "Lazy"
197+ ( l
198+ [ QApp (qVar "f")
199+ (QApp (qConst "List") (qVar "a"))
200+ ]
201+ )
202+ ( QFun (QApp (qVar "f") (qVar "a"))
203+ ( QApp (qVar "f")
204+ (QApp (qConst "List") (qVar "a"))
205+ )
206+ )
207+ )
208+ )
209+ )
210+
211+ it "test #28" do
168212 let input = "forall f a. Alternative f => Lazy(f (List a))=>f a -> f (List a)"
169− assertRight (parseTypeQuery input) ((QForAll (nl "f" ["a"]))
170− (QConstraint "Alternative" (l [QVar "f"])
171− (QConstraint "Lazy" (l [QApp (QVar "f")
172− (QApp (QConst "List") (QVar "a"))])
173− (QFun (QApp (QVar "f") (QVar "a"))
174− (QApp (QVar "f")
175− (QApp (QConst "List") (QVar "a")))))))
176−
177− test "test #29" do
213+ assertRight (parseTypeQuery input)
214+ ( (QForAll (nl "f" [ "a" ]))
215+ ( qConstraint "Alternative" (l [ qVar "f" ])
216+ ( qConstraint "Lazy"
217+ ( l
218+ [ QApp (qVar "f")
219+ (QApp (qConst "List") (qVar "a"))
220+ ]
221+ )
222+ ( QFun (QApp (qVar "f") (qVar "a"))
223+ ( QApp (qVar "f")
224+ (QApp (qConst "List") (qVar "a"))
225+ )
226+ )
227+ )
228+ )
229+ )
230+
231+ it "test #29" do
178232 let input = "{a::Int,b::Int}"
179233 assertRight (parseTypeQuery input)
180− (QApp (QConst "Record") (QRow (List.fromFoldable [ Tuple "a" (QConst "Int"), Tuple "b" (QConst "Int")])))
181−
182− test "test #30" do
234+ ( QApp (qConst "Record")
235+ ( QRow
236+ ( List.fromFoldable
237+ [ Tuple (Identifier "a") (qConst "Int")
238+ , Tuple (Identifier "b") (qConst "Int")
239+ ]
240+ )
241+ )
242+ )
243+
244+ it "test #30" do
183245 let input = "{record''' :: Int}"
184246 assertRight (parseTypeQuery input)
185− (QApp (QConst "Record") (QRow (List.fromFoldable [ Tuple "record'''" (QConst "Int")])))
247+ (QApp (qConst "Record") (QRow (List.fromFoldable [ Tuple (Identifier "record'''") (qConst "Int") ])))
186248
187− test "test #31" do
249+ it "test #31" do
188250 let input = "(row''' :: Int)"
189251 assertRight (parseTypeQuery input)
190− (QRow (List.fromFoldable [ Tuple "row'''" (QConst "Int")]))
252+ (QRow (List.fromFoldable [ Tuple (Identifier "row'''") (qConst "Int") ]))
191253
192− test "test #32" do
254+ it "test #32" do
193255 let input = "(row1 :: Int, row2 :: (),row3::(row4::{}))"
194256 assertRight (parseTypeQuery input)
195− (QRow (l [ Tuple "row1" (QConst "Int")
196− , Tuple "row2" (QRow Nil)
197− , Tuple "row3" (QRow (l [ Tuple "row4" (QApp (QConst "Record") (QRow Nil)) ])) ]))
198−
199− test "test #33" do
257+ ( QRow
258+ ( l
259+ [ Tuple (Identifier "row1") (qConst "Int")
260+ , Tuple (Identifier "row2") (QRow Nil)
261+ , Tuple (Identifier "row3") (QRow (l [ Tuple (Identifier "row4") (QApp (qConst "Record") (QRow Nil)) ]))
262+ ]
263+ )
264+ )
265+
266+ it "test #33" do
200267 let input = "Foldable1 t => Apply f => t (f a) -> f Unit"
201268 assertRight (parseTypeQuery input)
202− (QConstraint "Foldable1" ((QVar "t") : Nil) (QConstraint "Apply" ((QVar "f") : Nil) (QFun (QApp (QVar "t") (QApp (QVar "f") (QVar "a"))) (QApp (QVar "f") (QConst "Unit")))))
269+ (qConstraint "Foldable1" ((qVar "t") : Nil) (qConstraint "Apply" ((qVar "f") : Nil) (QFun (QApp (qVar "t") (QApp (qVar "f") (qVar "a"))) (QApp (qVar "f") (qConst "Unit")))))
203270
204− test "test #34" do
271+ it "test #34" do
205272 let input = "Foldable1 t => Apply f => t (f a) -> f a"
206273 assertRight (parseTypeQuery input)
207− (QConstraint "Foldable1" ((QVar "t") : Nil) (QConstraint "Apply" ((QVar "f") : Nil) (QFun (QApp (QVar "t") (QApp (QVar "f") (QVar "a"))) (QApp (QVar "f") (QVar "a")))))
274+ (qConstraint "Foldable1" ((qVar "t") : Nil) (qConstraint "Apply" ((qVar "f") : Nil) (QFun (QApp (qVar "t") (QApp (qVar "f") (qVar "a"))) (QApp (qVar "f") (qVar "a")))))
208275
209− test "test #35" do
276+ it "test #35" do
210277 let input = "Generic a rep => GenericEq rep => a -> a -> Boolean"
211278 assertRight (parseTypeQuery input)
212− (QConstraint "Generic" ((QVar "a") : (QVar "rep") : Nil)
213− (QConstraint "GenericEq" ((QVar "rep") : Nil)
214− (QFun (QVar "a") (QFun (QVar "a") (QConst "Boolean")))))
279+ ( qConstraint "Generic" ((qVar "a") : (qVar "rep") : Nil)
280+ ( qConstraint "GenericEq" ((qVar "rep") : Nil)
281+ (QFun (qVar "a") (QFun (qVar "a") (qConst "Boolean")))
282+ )
283+ )
215284
216− suite "polish notation" do
285+ describe "polish notation" do
217286
218− test "test #1" do
287+ it "test #1" do
219288 let input = "(a -> b) -> (b -> ((a -> b) -> c))"
220289 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
221− (l [ PForAll 3, PFun, PFun, PVar, PVar, PFun, PVar, PFun, PFun
222− , PVar, PVar, PVar ])
223−
224− test "test #2" do
290+ ( l
291+ [ PForAll 3
292+ , PFun
293+ , PFun
294+ , PVar
295+ , PVar
296+ , PFun
297+ , PVar
298+ , PFun
299+ , PFun
300+ , PVar
301+ , PVar
302+ , PVar
303+ ]
304+ )
305+
306+ it "test #2" do
225307 let input = "forall a. (a -> b) -> (b -> ((a -> b) -> c))"
226308 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
227− (l [ PForAll 3, PFun, PFun, PVar, PVar, PFun, PVar, PFun, PFun
228− , PVar, PVar, PVar ])
229−
230− test "test #3" do
309+ ( l
310+ [ PForAll 3
311+ , PFun
312+ , PFun
313+ , PVar
314+ , PVar
315+ , PFun
316+ , PVar
317+ , PFun
318+ , PFun
319+ , PVar
320+ , PVar
321+ , PVar
322+ ]
323+ )
324+
325+ it "test #3" do
231326 let input = "forall a. (a -> b) -> (b -> ((a -> b) -> c))"
232327 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
233− (l [ PForAll 3, PFun, PFun, PVar, PVar, PFun, PVar, PFun, PFun
234− , PVar, PVar, PVar ])
235−
236− test "test #4" do
328+ ( l
329+ [ PForAll 3
330+ , PFun
331+ , PFun
332+ , PVar
333+ , PVar
334+ , PFun
335+ , PVar
336+ , PFun
337+ , PFun
338+ , PVar
339+ , PVar
340+ , PVar
341+ ]
342+ )
343+
344+ it "test #4" do
237345 let input = "forall a. (forall h. ST h (STArray h a)) -> Array a"
238346 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
239− (l [ PForAll 1, PFun, PForAll 1, PApp, PApp, PVar, PVar, PApp, PApp, PVar, PVar, PVar, PApp, PVar, PVar ])
240−
241− suite "type shapes" do
242− test "test #1" do
243− let query = "Generic a rep => GenericEq rep => a -> a -> Boolean"
244− c1 = constr (qname [""] "Generic") [TypeVar "a", TypeVar "rep"]
245− c2 = constr (qname [""] "GenericEq") [TypeVar "rep"]
246−
247− fun t1 t2 =
248− TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Prim"]
249− , name: "Function" })) t1) t2
250− type_ =
251− ForAll "a" Nothing $
252− ForAll "rep" Nothing $
253− ConstrainedType c1
254− (ConstrainedType c2
255− (fun (TypeVar "a") (fun (TypeVar "b")
256− (TypeConstructor $ qname ["Prim", "Boolean"] "Boolean"))))
257− shape = shapeOfTypeQuery <$> parseTypeQuery query
258− Assert.equal (pure $ shapeOfType type_) shape
259−
260− suite "free variable counting" do
261−
262− test "test #1" do
347+ (l [ PForAll 1, PFun, PForAll 1, PApp, PApp, PVar, PVar, PApp, PApp, PVar, PVar, PVar, PApp, PVar, PVar ])
348+
349+ describe "type shapes" do
350+ it "test #1" do
351+ let
352+ query = "Generic a rep => GenericEq rep => a -> a -> Boolean"
353+ c1 = constr (qname [ "" ] "Generic") [ TypeVar "a", TypeVar "rep" ]
354+ c2 = constr (qname [ "" ] "GenericEq") [ TypeVar "rep" ]
355+
356+ fun t1 t2 =
357+ TypeApp
358+ ( TypeApp
359+ ( TypeConstructor
360+ ( QualifiedName
361+ { moduleNameParts: [ "Prim" ]
362+ , name: Identifier "Function"
363+ }
364+ )
365+ )
366+ t1
367+ )
368+ t2
369+ type_ =
370+ ForAll "a" Nothing
371+ $ ForAll "rep" Nothing
372+ $
373+ ConstrainedType c1
374+ ( ConstrainedType c2
375+ ( fun (TypeVar "a")
376+ ( fun (TypeVar "b")
377+ (TypeConstructor $ qname [ "Prim", "Boolean" ] "Boolean")
378+ )
379+ )
380+ )
381+ shape = shapeOfTypeQuery <$> parseTypeQuery query
382+ pure (shapeOfType type_) `shouldEqual` shape
383+
384+ describe "free variable counting" do
385+
386+ it "test #1" do
263387 let input = "forall a. (a -> b) -> (b -> ((a -> b) -> c))"
264388 assertRight (countFreeVars <$> parseTypeQuery input) 2
265389
266− test "test #2" do
390+ it "test #2" do
267391 -- `b` is not bound on the left, `a` is not bound on the right
268392 let input = "(forall a. (a -> b)) -> forall b. (b -> a)"
269393 assertRight (countFreeVars <$> parseTypeQuery input) 2
270394
271− test "test #3" do
395+ it "test #3" do
272396 let input = "a -> forall a. a"
273397 assertRight (countFreeVars <$> parseTypeQuery input) 1
274398
275− test "test #4" do
399+ it "test #4" do
276400 let input = "(forall a. a) -> a"
277401 assertRight (countFreeVars <$> parseTypeQuery input) 1
278402
279− test "test #5" do
403+ it "test #5" do
280404 let input = "forall a. a -> a"
281405 assertRight (countFreeVars <$> parseTypeQuery input) 0
282406
283− test "test #6" do
407+ it "test #6" do
284408 let input = "a -> b -> c"
285409 assertRight (countFreeVars <$> parseTypeQuery input) 3
286410
287− test "test #7" do
411+ it "test #7" do
288412 let input = "forall m a. Monad m => a -> m a"
289413 assertRight (countFreeVars <$> parseTypeQuery input) 0
290414
291− test "test #8" do
415+ it "test #8" do
292416 let input = "Monad m => a -> m a"
293417 assertRight (countFreeVars <$> parseTypeQuery input) 2
294418
295− test "test #9" do
419+ it "test #9" do
296420 let input = "Monad m => a -> a"
297421 assertRight (countFreeVars <$> parseTypeQuery input) 2
298422
299− test "test #10" do
423+ it "test #10" do
300424 let input = "forall a. (forall a. a) a"
301425 assertRight (countFreeVars <$> parseTypeQuery input) 0
302426
303− test "test #11" do
427+ it "test #11" do
304428 let input = "forall a. (forall b. a) a"
305429 assertRight (countFreeVars <$> parseTypeQuery input) 0
306430
307− test "test #12" do
431+ it "test #12" do
308432 let input = "forall a. (forall b. a) a b"
309433 assertRight (countFreeVars <$> parseTypeQuery input) 1
310434
311− suite "typeVarPenalty" do
312−
313− test "#0" do
314− Assert.equal 0 (typeVarPenalty mempty)
315−
316− test "#1" do
317− Assert.equal 0 (typeVarPenalty $ l [ Substitute "a" "b"
318− , Substitute "b" "a"
319− ])
320−
321− test "#2" do
322− Assert.equal 0 (typeVarPenalty $ l [ Substitute "a" "b"
323− , Substitute "a" "b"
324− , Substitute "a" "b"
325− ])
326−
327− test "#3" do
328− Assert.equal 1 (typeVarPenalty $ l [ Substitute "a" "b"
329− , Substitute "a" "c"
330− ])
331−
332− test "#4" do
333− Assert.equal 1 (typeVarPenalty $ l [ Substitute "a" "b"
334− , Substitute "b" "a"
335− , Substitute "b" "c"
336− ])
337−
338− test "#5" do
339− Assert.equal 0 (typeVarPenalty $ l [ Substitute "a" "b"
340− , Substitute "b" "c"
341− , Substitute "c" "a"
342− ])
343−
344− test "#6" do
345− Assert.equal 2 (typeVarPenalty $ l [ Substitute "a" "b"
346− , Substitute "a" "c"
347− , Substitute "a" "a"
348− ])
349−
350− test "#7" do
351− Assert.equal 2 (typeVarPenalty $ l [ Substitute "a" "a"
352− , Substitute "b" "a"
353− , Substitute "c" "a"
354− ])
355−
356− test "#8" do
357− Assert.equal 4 (typeVarPenalty $ l [ Substitute "a" "a"
358− , Substitute "b" "a"
359− , Substitute "c" "a"
360− , Substitute "a" "b"
361− , Substitute "a" "c"
362− , Substitute "a" "a"
363− ])
364−
365− test "#9" do
366− Assert.equal 0 (typeVarPenalty $ l [ Substitute "a" "e"
367− , Substitute "b" "d"
368− , Substitute "c" "f"
369− ])
370−
371− suite "unification" do
372− test "instantiation #0" do
373− let mVarQuery = QVar "m"
374− unitConstQuery = QConst "Unit"
375−
376− Assert.assert "instantiation #0" $
377− (penalty unitConstQuery unitType < penalty mVarQuery unitType)
378−
379− test "generalization #0" do
380− let query = QVar "m"
381− t1 = TypeVar "m"
382−
383− Assert.assert "qeneralization #0" $
384− (penalty query unitType > penalty query t1)
385−
435+ describe "typeVarPenalty" do
436+
437+ it "#0" do
438+ 0 `shouldEqual` (typeVarPenalty mempty)
439+
440+ it "#1" do
441+ 0 `shouldEqual`
442+ ( typeVarPenalty $ l
443+ [ substitute "a" "b"
444+ , substitute "b" "a"
445+ ]
446+ )
447+
448+ it "#2" do
449+ 0 `shouldEqual`
450+ ( typeVarPenalty $ l
451+ [ substitute "a" "b"
452+ , substitute "a" "b"
453+ , substitute "a" "b"
454+ ]
455+ )
456+
457+ it "#3" do
458+ 1 `shouldEqual`
459+ ( typeVarPenalty $ l
460+ [ substitute "a" "b"
461+ , substitute "a" "c"
462+ ]
463+ )
464+
465+ it "#4" do
466+ 1 `shouldEqual`
467+ ( typeVarPenalty $ l
468+ [ substitute "a" "b"
469+ , substitute "b" "a"
470+ , substitute "b" "c"
471+ ]
472+ )
473+
474+ it "#5" do
475+ 0 `shouldEqual`
476+ ( typeVarPenalty $ l
477+ [ substitute "a" "b"
478+ , substitute "b" "c"
479+ , substitute "c" "a"
480+ ]
481+ )
482+
483+ it "#6" do
484+ 2 `shouldEqual`
485+ ( typeVarPenalty $ l
486+ [ substitute "a" "b"
487+ , substitute "a" "c"
488+ , substitute "a" "a"
489+ ]
490+ )
491+
492+ it "#7" do
493+ 2 `shouldEqual`
494+ ( typeVarPenalty $ l
495+ [ substitute "a" "a"
496+ , substitute "b" "a"
497+ , substitute "c" "a"
498+ ]
499+ )
500+
501+ it "#8" do
502+ 4 `shouldEqual`
503+ ( typeVarPenalty $ l
504+ [ substitute "a" "a"
505+ , substitute "b" "a"
506+ , substitute "c" "a"
507+ , substitute "a" "b"
508+ , substitute "a" "c"
509+ , substitute "a" "a"
510+ ]
511+ )
512+
513+ it "#9" do
514+ 0 `shouldEqual`
515+ ( typeVarPenalty $ l
516+ [ substitute "a" "e"
517+ , substitute "b" "d"
518+ , substitute "c" "f"
519+ ]
520+ )
521+
522+ describe "unification" do
523+ it "instantiation #0" do
524+ let
525+ mVarQuery = qVar "m"
526+ unitConstQuery = qConst "Unit"
527+
528+ shouldSatisfy
529+ (penalty unitConstQuery unitType)
530+ (_ < penalty mVarQuery unitType)
531+
532+ it "generalization #0" do
533+ let
534+ query = qVar "m"
535+ t1 = TypeVar "m"
536+
537+ shouldSatisfy
538+ (penalty query unitType)
539+ (_ > penalty query t1)
386540
387541l :: forall f. Foldable f => (forall a. f a -> List a)
388542l = List.fromFoldable
389543
390−nl :: forall t5 t6. Foldable t6 => t5 -> t6 t5 -> NonEmptyList t5
391−nl x rst = NonEmptyList.cons' x $ List.fromFoldable rst
544+nl
545+ :: forall t
546+ . Foldable t
547+ => Functor t
548+ => String
549+ -> t String
550+ -> NonEmptyList Identifier
551+nl x rst = NonEmptyList.cons' (Identifier x) $ List.fromFoldable (rst <#> Identifier)
392552
393553unitType :: Type
394−unitType = TypeConstructor (QualifiedName { moduleName: []
395− , name: "Unit"
396− })
554+unitType = TypeConstructor
555+ ( QualifiedName
556+ { moduleNameParts: []
557+ , name: Identifier "Unit"
558+ }
559+ )
397560
398561countFreeVars :: TypeQuery -> Int
399562countFreeVars = getFreeVariables >>> Set.size
400563
401564qname :: Array String -> String -> QualifiedName
402−qname m n = QualifiedName { moduleName: m, name: n }
565+qname m n = QualifiedName { moduleNameParts: m, name: Identifier n }
403566
404567constr :: QualifiedName -> Array Type -> Constraint
405568constr c a = Constraint { constraintClass: c, constraintArgs: a }
569+
570+qVar :: String -> TypeQuery
571+qVar = QVar <<< Identifier
572+
573+qConst :: String -> TypeQuery
574+qConst = QConst <<< Identifier
575+
576+qConstraint :: String -> List TypeQuery -> TypeQuery -> TypeQuery
577+qConstraint = QConstraint <<< Identifier
578+
579+substitute :: String -> String -> Substitution
580+substitute a b = Substitute (Identifier a) (Identifier b)
test/Test/UI.pursnew file+68
@@ -0,0 +1,68 @@
1+module Test.UI where
2+
3+-- import Prelude
4+
5+-- import Data.Array as Array
6+-- import Data.Foldable (for_)
7+-- import Data.Newtype (unwrap)
8+-- import Effect (Effect)
9+-- import Effect.Aff (Aff, launchAff_)
10+-- import Effect.Class (liftEffect)
11+-- import Effect.Console as Console
12+-- import Foreign (Foreign)
13+-- import Foreign as Foreign
14+-- import Node.FS.Sync (realpath)
15+-- import Test.Spec.Assertions (shouldSatisfy)
16+-- -- import Toppokki as T
17+-- -- import Playwright as P
18+
19+-- main :: Effect Unit
20+-- main = launchAff_ do
21+-- pure unit
22+-- path <- liftEffect $ realpath "."
23+
24+-- let indexHTML = T.URL $ "file://" <> path <> "/generated-docs/html/index.html"
25+-- prim = T.URL $ "file://" <> path <> "/generated-docs/html/Prim.html"
26+-- docsSearch = T.URL $ "file://" <> path <> "/generated-docs/html/Docs.Search.App.html"
27+
28+-- for_ [ indexHTML, prim, docsSearch ] \url -> do
29+-- withPage url \page -> do
30+-- void $ T.pageWaitForSelector (T.Selector "#group-modules__label") { timeout: 10000 } page
31+-- log $ "has module grouping: " <> unwrap url
32+
33+-- withPage url \page -> do
34+-- T.keyboardPress (T.KeyboardKey "s") {} page
35+-- void $ T.keyboardType "slice" {} page
36+-- T.keyboardPress (T.KeyboardKey "Enter") {} page
37+-- void $ T.pageWaitForSelector (T.Selector ".result__actions__item") { timeout: 10000 } page
38+-- log $ "has working search field: " <> unwrap url
39+
40+-- withPage url \page -> do
41+-- T.keyboardPress (T.KeyboardKey "s") {} page
42+-- void $ T.keyboardType "a -> b" {} page
43+-- T.keyboardPress (T.KeyboardKey "Enter") {} page
44+-- void $ T.pageWaitForSelector (T.Selector ".result__actions__item") { timeout: 10000 } page
45+-- arr <- readStringArray <$> T.unsafeEvaluateStringFunction getResultTitlesCode page
46+-- arr `shouldSatisfy` (Array.elem "unsafeCoerce")
47+-- log $ "is able to find unsafeCoerce by type: " <> unwrap url
48+
49+-- withPage (T.URL $ unwrap url <> "#search:unsafeCoerce") \page -> do
50+-- void $ T.pageWaitForSelector (T.Selector ".result__actions__item") { timeout: 10000 } page
51+-- arr <- readStringArray <$> T.unsafeEvaluateStringFunction getResultTitlesCode page
52+-- arr `shouldSatisfy` (Array.elem "unsafeCoerce")
53+-- log $ "can read URI hash: " <> unwrap url
54+
55+-- where
56+-- log = liftEffect <<< Console.log
57+-- getResultTitlesCode = "[].map.call(document.querySelectorAll('.result__title'), el => el.textContent)"
58+-- readStringArray :: Foreign -> Array String
59+-- readStringArray = Foreign.unsafeFromForeign
60+
61+
62+-- withPage :: forall a. T.URL -> (T.Page -> Aff a) -> Aff Unit
63+-- withPage url f = do
64+-- browser <- T.launch {}
65+-- page <- T.newPage browser
66+-- T.goto url page
67+-- void $ f page
68+-- T.close browser