git.iko.soy/rowtype-yoga/purescript-docs-search
on master help sign in
.github/workflows/build.ymlnew file+44
since splitsnapshots
unifiedsplit
@@ -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.
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
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+
8## [0.0.6 - 2019-11-29]
57## [0.0.6 - 2019-11-29]
9
58
10New features:
59New features:
README.md+4−4
@@ -1,8 +1,8 @@
1# purescript-docs-search
1# purescript-docs-search
2
2
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)
4
4
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.
6
6
7It supports nearly-all functionality of [Pursuit](https://github.com/purescript/pursuit), including querying by type.
7It supports nearly-all functionality of [Pursuit](https://github.com/purescript/pursuit), including querying by type.
8
8
@@ -10,7 +10,7 @@ It supports nearly-all functionality of [Pursuit](https://github.com/purescript/
10
10
11When using [spago](https://github.com/spacchetti/spago), you don't need to install this app manually: run `spago docs` or `spago search`.
11When using [spago](https://github.com/spacchetti/spago), you don't need to install this app manually: run `spago docs` or `spago search`.
12
12
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`.
14
14
15## Usage
15## Usage
16
16
@@ -45,4 +45,4 @@ npm install
45npm run build # or build-dev to skip JS compression stage
45npm run build # or build-dev to skip JS compression stage
46```
46```
47
47
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 @@
1{
1{
2 "name": "purescript-docs-search",
2 "name": "purescript-docs-search",
3+ "type": "module",
3− "version": "0.0.8",
4+ "version": "0.0.12",
4 "description": "Search frontend for the documentation generated by the PureScript compiler.",
5 "description": "Search frontend for the documentation generated by the PureScript compiler.",
5 "directories": {
6 "directories": {
6 "test": "test"
7 "test": "test"
7 },
8 },
8 "bin": {
9 "bin": {
9− "purescript-docs-search": "dist/purescript-docs-search"
10+ "purescript-docs-search": "dist/purescript-docs-search.cjs"
10 },
11 },
11 "files": [
12 "files": [
12− "dist/purescript-docs-search",
13+ "dist/purescript-docs-search.cjs",
13 "dist/docs-search-app.js",
14 "dist/docs-search-app.js",
14 "README.md",
15 "README.md",
15 "CHANGELOG.md"
16 "CHANGELOG.md"
16 ],
17 ],
17 "scripts": {
18 "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",
19 "bundle-app": "spago bundle-app --no-build --no-install -m Docs.Search.App --to dist/docs-search-app.js",
20 "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+ "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",
21− "build-app": "npm run bundle-app && npm run parcel-app",
22+ "build-app": "npm run bundle-app && npm run esbuild-app",
22− "bundle-main": "spago bundle-app --no-build --no-install -m Docs.Search.Main --to dist/main.js",
23+ "bundle-main": "spago bundle-app --no-build --no-install --platform node -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+ "esbuild-main": "esbuild dist/main.js --platform=node --bundle --minify --outfile=dist/main.min.js && mv dist/main.min.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+ "add-shebang": "echo \"#!/usr/bin/env node\" > dist/purescript-docs-search.cjs && cat dist/main.js >> dist/purescript-docs-search.cjs",
25− "chmod-main": "chmod +x dist/purescript-docs-search",
26+ "chmod-main": "chmod +x dist/purescript-docs-search.cjs",
26− "build-main": "npm run bundle-main && npm run parcel-main && npm run add-shebang && rm dist/main.js && npm run chmod-main",
27+ "build-main": "npm run bundle-main && npm run esbuild-main && npm run add-shebang && rm dist/main.js && npm run chmod-main",
27 "build": "spago build && npm run build-app && npm run build-main",
28 "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",
29 "clean": "rm -rf dist",
29 "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\" ]"
31 },
31 },
32 "repository": {
32 "repository": {
33 "type": "git",
33 "type": "git",
34− "url": "git+https://github.com/spacchetti/purescript-docs-search.git"
34+ "url": "git+https://github.com/purescript/purescript-docs-search.git"
35 },
35 },
36 "keywords": [
36 "keywords": [
37 "purescript"
37 "purescript"
@@ -39,14 +39,17 @@
39 "author": "Kalnitsky Vladimir <klntsky@gmail.com>",
39 "author": "Kalnitsky Vladimir <klntsky@gmail.com>",
40 "license": "BSD-3-Clause",
40 "license": "BSD-3-Clause",
41 "bugs": {
41 "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"
43 },
47 },
44− "homepage": "https://github.com/spacchetti/purescript-docs-search#readme",
45− "dependencies": {},
46 "devDependencies": {
48 "devDependencies": {
49+ "esbuild": "^0.11.10",
47 "glob": "^7.1.6",
50 "glob": "^7.1.6",
48− "markdown-it": "^11.0.0",
51+ "markdown-it": "^12.0.4",
49− "parcel": "^1.12.4",
52+ "puppeteer": "^8.0.0",
50− "spago": "^0.15.3"
53+ "spago": "^0.20.9"
51 }
54 }
52}
55}
packages.dhall+114−26
@@ -1,10 +1,12 @@
1let mkPackage =
1let 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
3
4
4let upstream =
5let 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
6
8
7−let overrides = { metadata = upstream.metadata // { version = "v0.13.0" } }
9+let overrides = {=}
8
10
9let additions =
11let additions =
10 { halogen =
12 { halogen =
@@ -13,12 +15,13 @@ let additions =
13 , "avar"
15 , "avar"
14 , "console"
16 , "console"
15 , "const"
17 , "const"
16− , "coroutines"
17 , "dom-indexed"
18 , "dom-indexed"
19+ , "effect"
18 , "foreign"
20 , "foreign"
19 , "fork"
21 , "fork"
20 , "free"
22 , "free"
21 , "freeap"
23 , "freeap"
24+ , "halogen-subscriptions"
22 , "halogen-vdom"
25 , "halogen-vdom"
23 , "media-types"
26 , "media-types"
24 , "nullable"
27 , "nullable"
@@ -28,15 +31,24 @@ let additions =
28 , "transformers"
31 , "transformers"
29 , "unsafe-coerce"
32 , "unsafe-coerce"
30 , "unsafe-reference"
33 , "unsafe-reference"
34+ , "web-file"
31 , "web-uievents"
35 , "web-uievents"
32 ]
36 ]
33− "https://github.com/slamdata/purescript-halogen.git"
37+ "https://github.com/purescript-halogen/purescript-halogen.git"
34− "v5.0.0-rc.6"
38+ "v7.0.0"
35− , halogen-css =
39+ , memoize =
36 mkPackage
40 mkPackage
37− [ "css", "halogen" ]
41+ [ "prelude"
42+ , "lazy"
43+ , "either"
44+ , "maybe"
45+ , "tuples"
46+ , "integers"
47+ , "lists"
48+ , "strings"
49+ ]
38− "https://github.com/slamdata/purescript-halogen-css.git"
50+ "https://github.com/paf31/purescript-memoize.git"
39− "v8.0.0"
51+ "9960694e82adc212fd89f8ed8778cf55fcb72aeb"
40 , optparse =
52 , optparse =
41 mkPackage
53 mkPackage
42 [ "prelude"
54 [ "prelude"
@@ -46,14 +58,14 @@ let additions =
46 , "ordered-collections"
58 , "ordered-collections"
47 , "arrays"
59 , "arrays"
48 , "console"
60 , "console"
49− , "memoize"
50 , "transformers"
61 , "transformers"
51 , "exists"
62 , "exists"
52 , "node-process"
63 , "node-process"
53 , "free"
64 , "free"
65+ , "memoize"
54 ]
66 ]
55− "https://github.com/f-o-a-m/purescript-optparse.git"
67+ "https://github.com/klntsky/purescript-optparse.git"
56− "v3.0.1"
68+ "2fe4265b7c6b09744c11190a43ca06777c752473"
57 , exitcodes =
69 , exitcodes =
58 mkPackage
70 mkPackage
59 [ "enums" ]
71 [ "enums" ]
@@ -62,33 +74,109 @@ let additions =
62 , markdown-it =
74 , markdown-it =
63 mkPackage
75 mkPackage
64 [ "prelude", "effect", "options" ]
76 [ "prelude", "effect", "options" ]
65− "https://github.com/nonbili/purescript-markdown-it.git"
77+ "https://github.com/klntsky/purescript-markdown-it.git"
66− "v0.4.0"
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"
67 , html-parser-halogen =
103 , html-parser-halogen =
68 mkPackage
104 mkPackage
69− [ "string-parsers", "generics-rep", "halogen" ]
105+ [ "string-parsers", "halogen" ]
70 "https://github.com/rnons/purescript-html-parser-halogen.git"
106 "https://github.com/rnons/purescript-html-parser-halogen.git"
71− "890da763cdd2a1049ab8837e477c5ba1fcf6d4ce"
107+ "035a51d02ba9f8b70c3ffd9fe31a3f5bed19941c"
72 , markdown-it-halogen =
108 , markdown-it-halogen =
73 mkPackage
109 mkPackage
74 [ "markdown-it", "html-parser-halogen" ]
110 [ "markdown-it", "html-parser-halogen" ]
75 "https://github.com/nonbili/purescript-markdown-it-halogen.git"
111 "https://github.com/nonbili/purescript-markdown-it-halogen.git"
76 "08c9625015bf04214be14e45230e8ce12f3fa2bf"
112 "08c9625015bf04214be14e45230e8ce12f3fa2bf"
77− , bower-json =
113+ , search-trie =
78 mkPackage
114 mkPackage
79 [ "prelude"
115 [ "prelude"
80− , "generics-rep"
81− , "maybe"
82 , "arrays"
116 , "arrays"
83− , "either"
117+ , "ordered-collections"
84− , "newtype"
118+ , "lists"
85− , "tuples"
86 , "foldable-traversable"
119 , "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"
88 , "foreign-object"
170 , "foreign-object"
171+ , "literals"
172+ , "maybe"
173+ , "newtype"
174+ , "psci-support"
175+ , "tuples"
176+ , "unsafe-coerce"
89 ]
177 ]
90− "https://github.com/klntsky/purescript-bower-json.git"
178+ "https://github.com/jvliwanag/purescript-untagged-union.git"
91− "v1.0.0"
179+ "ed8262a966e15e751322c327e2759a9b9c0ef3f3"
92 }
180 }
93
181
94in upstream // overrides // additions
182in 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" ]
1+{ sources = [ "src/**/*.purs", "test/**/*.purs" ]
3−, name =
4− "docs-search"
2+, name = "docs-search"
5, dependencies =
3, dependencies =
4+ [ "aff"
6− [ "aff-promise"
5+ , "aff-promise"
7− , "argonaut-codecs"
6+ , "argonaut-codecs"
8− , "argonaut-core"
7+ , "argonaut-core"
9− , "argonaut-generic"
8+ , "argonaut-generic"
10− , "arrays"
9+ , "arrays"
11− , "bower-json"
10+ , "bower-json"
12− , "console"
11+ , "console"
13− , "control"
12+ , "control"
14− , "coroutines"
13+ , "css"
15− , "effect"
14+ , "effect"
15+ , "either"
16+ , "exceptions"
16− , "foldable-traversable"
17+ , "foldable-traversable"
17− , "generics-rep"
18+ , "foreign-object"
18− , "halogen"
19+ , "halogen"
19− , "halogen-css"
20+ , "halogen-css"
21+ , "halogen-subscriptions"
22+ , "identity"
23+ , "js-uri"
20− , "lists"
24+ , "lists"
21− , "markdown-it"
25+ , "markdown-it"
22− , "markdown-it-halogen"
26+ , "markdown-it-halogen"
23− , "maybe"
27+ , "maybe"
24− , "newtype"
28+ , "newtype"
25− , "node-buffer"
29+ , "node-buffer"
26− , "node-fs"
30+ , "node-fs"
27− , "node-fs-aff"
31+ , "node-fs-aff"
28− , "node-process"
32+ , "node-process"
29− , "node-readline"
33+ , "node-readline"
30− , "optparse"
34+ , "optparse"
35+ , "ordered-collections"
36+ , "parallel"
37+ , "partial"
38+ , "prelude"
31− , "profunctor"
39+ , "profunctor"
32− , "profunctor-lenses"
40+ , "profunctor-lenses"
33− , "search-trie"
41+ , "search-trie"
42+ , "spec"
34− , "string-parsers"
43+ , "string-parsers"
35− , "strings"
44+ , "strings"
36− , "test-unit"
45+ , "transformers"
46+ , "tuples"
47+ , "unfoldable"
37− , "web-dom"
48+ , "web-dom"
49+ , "web-events"
38− , "web-html"
50+ , "web-html"
39− , "web-storage"
51+ , "web-storage"
52+ , "web-uievents"
40− ]
53+ ]
41−, packages =
42− ./packages.dhall
54+, packages = ./packages.dhall
43}
55}
src/Docs/Search/App.purs+54−39
@@ -1,29 +1,33 @@
1-- | This is the main module of the client-side Halogen app.
1-- | This is the main module of the client-side Halogen app.
2module Docs.Search.App where
2module Docs.Search.App where
3
3
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+
4import Prelude
13import Prelude
5
14
6import Control.Alt (alt)
15import Control.Alt (alt)
7−import Control.Coroutine as Coroutine
8import Data.Maybe (Maybe(..))
16import Data.Maybe (Maybe(..))
9import Data.Newtype (wrap)
17import Data.Newtype (wrap)
18+import Data.Map as Map
10import Data.Tuple (Tuple(..))
19import Data.Tuple (Tuple(..))
11import Data.Tuple.Nested ((/\))
20import 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
19import Effect (Effect)
21import Effect (Effect)
20import Effect.Aff (launchAff_)
22import Effect.Aff (launchAff_)
21import Halogen as H
23import Halogen as H
22import Halogen.Aff as HA
24import Halogen.Aff as HA
25+import Halogen.Subscription (subscribe)
23import Halogen.VDom.Driver (runUI)
26import Halogen.VDom.Driver (runUI)
24import MarkdownIt as MD
27import MarkdownIt as MD
25import Web.DOM.ChildNode as ChildNode
28import Web.DOM.ChildNode as ChildNode
26import Web.DOM.Document as Document
29import Web.DOM.Document as Document
30+import Web.DOM.Document (Document)
27import Web.DOM.Element as Element
31import Web.DOM.Element as Element
28import Web.DOM.Node as Node
32import Web.DOM.Node as Node
29import Web.DOM.ParentNode as ParentNode
33import Web.DOM.ParentNode as ParentNode
@@ -39,12 +43,11 @@ import Web.HTML.Window as Window
39
43
40main :: Effect Unit
44main :: Effect Unit
41main = do
45main = do
42− win <- HTML.window
46+ window <- HTML.window
43− doc <- HTMLDocument.toDocument <$> Window.document win
44
47
45− insertStyle doc
48+ insertStyle
46− insertVersionInfo doc
49+ insertVersionInfo
47− mbContainers <- getContainers doc
50+ mbContainers <- getContainers
48
51
49 -- Initialize a `markdown-it` instance (we need it to render the docs as markdown)
52 -- Initialize a `markdown-it` instance (we need it to render the docs as markdown)
50 markdownIt <- MD.newMarkdownIt MD.Default mempty
53 markdownIt <- MD.newMarkdownIt MD.Default mempty
@@ -63,55 +66,62 @@ main = do
63 HA.runHalogenAff do
66 HA.runHalogenAff do
64 packageIndex <- PackageIndex.loadPackageIndex
67 packageIndex <- PackageIndex.loadPackageIndex
65 moduleIndex <- ModuleIndex.unpackModuleIndex <$> ModuleIndex.loadModuleIndex
68 moduleIndex <- ModuleIndex.unpackModuleIndex <$> ModuleIndex.loadModuleIndex
69+ meta <- Meta.load
66 let scores = PackageIndex.mkScoresFromPackageIndex packageIndex
70 let scores = PackageIndex.mkScoresFromPackageIndex packageIndex
67
71
68 let initialSearchEngineState = { packageIndex
72 let initialSearchEngineState = { packageIndex
69 , moduleIndex
73 , moduleIndex
70− , index: mempty
74+ , index: wrap Map.empty
71− , typeIndex: mempty
75+ , typeIndex: wrap Map.empty
72 , scores
76 , scores
73 }
77 }
74−
75 resultsComponent =
78 resultsComponent =
76− SearchResults.mkComponent initialSearchEngineState pageContents markdownIt
79+ SearchResults.mkComponent
80+ initialSearchEngineState
81+ pageContents
82+ markdownIt
83+ meta
77
84
78 sfio <- runUI SearchField.component unit searchField
85 sfio <- runUI SearchField.component unit searchField
79 srio <- runUI resultsComponent unit searchResults
86 srio <- runUI resultsComponent unit searchResults
80
87
81− sfio.subscribe $
88+ void $ H.liftEffect $ subscribe sfio.messages $ \sfm -> do
89+ launchAff_ $ void do
82− Coroutine.consumer (srio.query <<< H.tell <<< SearchResults.MessageFromSearchField)
90+ srio.query (SearchResults.MessageFromSearchField sfm unit)
83
91
84 -- We need to read the URI hash only when both components are initialized and
92 -- We need to read the URI hash only when both components are initialized and
85 -- the search field is subscribed to the main component.
93 -- the search field is subscribed to the main component.
86− void $ sfio.query $ H.tell SearchField.ReadURIHash
94+ void $ sfio.query $ SearchField.ReadURIHash unit
87
95
88 -- Subscribe to URI hash updates
96 -- Subscribe to URI hash updates
89 H.liftEffect do
97 H.liftEffect do
90
98
91 listener <-
99 listener <-
92− eventListener \event ->
100+ eventListener \_event ->
93− launchAff_ do
101+ launchAff_ $ void do
94− sfio.query $ H.tell SearchField.ReadURIHash
102+ sfio.query $ SearchField.ReadURIHash unit
95
103
96− addEventListener hashchange listener true (Window.toEventTarget win)
104+ addEventListener hashchange listener true (Window.toEventTarget window)
97
105
98 sbio <- do
106 sbio <- do
99− component <- Sidebar.mkComponent moduleIndex.packageModules isIndexHTML
107+ component <- Sidebar.mkComponent moduleIndex isIndexHTML meta
100− runUI component unit sidebarContainer
108+ runUI component unit sidebarContainer
101
109
102 -- Subscribe to window focus events
110 -- Subscribe to window focus events
103 H.liftEffect do
111 H.liftEffect do
104
112
105 listener <-
113 listener <-
106− eventListener \event ->
114+ eventListener \_event ->
107− launchAff_ do
115+ launchAff_ $ void do
108− sbio.query $ H.tell Sidebar.UpdateModuleGrouping
116+ sbio.query $ Sidebar.UpdateModuleGrouping unit
117+
118+ addEventListener focus listener true (Window.toEventTarget window)
109
119
110− addEventListener focus listener true (Window.toEventTarget win)
111
120
121+insertStyle :: Effect Unit
122+insertStyle = do
123+ doc <- getDocument
112
124
113−insertStyle :: Document.Document -> Effect Unit
114−insertStyle doc = do
115 let styleContents = """
125 let styleContents = """
116 .top-banner__actions {
126 .top-banner__actions {
117 width: 10%;
127 width: 10%;
@@ -176,8 +186,9 @@ insertStyle doc = do
176 void $ Node.appendChild (Element.toNode style) (Element.toNode head)
186 void $ Node.appendChild (Element.toNode style) (Element.toNode head)
177
187
178
188
179−insertVersionInfo :: Document.Document -> Effect Unit
189+insertVersionInfo :: Effect Unit
180−insertVersionInfo doc = do
190+insertVersionInfo = do
191+ doc <- getDocument
181 let docPN = Document.toParentNode doc
192 let docPN = Document.toParentNode doc
182 mbVersionInfo <-
193 mbVersionInfo <-
183 ParentNode.querySelector (wrap ".footer > p") docPN
194 ParentNode.querySelector (wrap ".footer > p") docPN
@@ -186,10 +197,10 @@ insertVersionInfo doc = do
186 prefix <- Document.createTextNode " - patched by " doc <#> Text.toNode
197 prefix <- Document.createTextNode " - patched by " doc <#> Text.toNode
187 linkElement <- Document.createElement "a" doc
198 linkElement <- Document.createElement "a" doc
188 let linkNode = Element.toNode linkElement
199 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
190 Element.setAttribute "target" "_blank" linkElement
201 Element.setAttribute "target" "_blank" linkElement
191 linkText <- Document.createTextNode ("docs-search") doc <#> Text.toNode
202 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
193 void $ Node.appendChild prefix versionInfo
204 void $ Node.appendChild prefix versionInfo
194 void $ Node.appendChild linkNode versionInfo
205 void $ Node.appendChild linkNode versionInfo
195 void $ Node.appendChild linkText linkNode
206 void $ Node.appendChild linkText linkNode
@@ -199,15 +210,15 @@ insertVersionInfo doc = do
199-- | Query the DOM for specific elements that should always be present and determine if we are on
210-- | Query the DOM for specific elements that should always be present and determine if we are on
200-- | `index.html` or not.
211-- | `index.html` or not.
201getContainers
212getContainers
202− :: Document.Document
203− -> Effect (Maybe { searchField :: HTML.HTMLElement
213+ :: Effect (Maybe { searchField :: HTML.HTMLElement
204 , searchResults :: HTML.HTMLElement
214 , searchResults :: HTML.HTMLElement
205 , pageContents :: Element.Element
215 , pageContents :: Element.Element
206 , sidebarContainer :: HTML.HTMLElement
216 , sidebarContainer :: HTML.HTMLElement
207 , realSidebar :: Element.Element
217 , realSidebar :: Element.Element
208 , isIndexHTML :: Sidebar.IsIndexHTML
218 , isIndexHTML :: Sidebar.IsIndexHTML
209 })
219 })
210−getContainers doc = do
220+getContainers = do
221+ doc <- getDocument
211 let docPN = Document.toParentNode doc
222 let docPN = Document.toParentNode doc
212 mbBanner <-
223 mbBanner <-
213 ParentNode.querySelector (wrap ".top-banner > .container") docPN
224 ParentNode.querySelector (wrap ".top-banner > .container") docPN
@@ -243,3 +254,7 @@ getContainers doc = do
243 , isIndexHTML
254 , isIndexHTML
244 }
255 }
245 | otherwise -> pure Nothing
256 | 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
15import Halogen.HTML.CSS as HS
15import Halogen.HTML.CSS as HS
16import Halogen.HTML.Events as HE
16import Halogen.HTML.Events as HE
17import Halogen.HTML.Properties as HP
17import Halogen.HTML.Properties as HP
18−import Halogen.Query.EventSource as ES
18+import Halogen.Query.Event as ES
19import Web.DOM.Document as Document
19import Web.DOM.Document as Document
20import Web.DOM.ParentNode as ParentNode
20import Web.DOM.ParentNode as ParentNode
21import Web.HTML as HTML
21import Web.HTML as HTML
@@ -36,6 +36,7 @@ data Action
36 | FocusChanged Boolean
36 | FocusChanged Boolean
37 | InitKeyboardListener
37 | InitKeyboardListener
38 | HandleKey H.SubscriptionId KeyboardEvent
38 | HandleKey H.SubscriptionId KeyboardEvent
39+ | NoOp
39
40
40data Query a
41data Query a
41 = ReadURIHash a
42 = ReadURIHash a
@@ -46,7 +47,7 @@ data SearchFieldMessage
46 | Focused
47 | Focused
47 | LostFocus
48 | LostFocus
48
49
49−component :: forall i. H.Component HH.HTML Query i SearchFieldMessage Aff
50+component :: forall i. H.Component Query i SearchFieldMessage Aff
50component =
51component =
51 H.mkComponent
52 H.mkComponent
52 { initialState
53 { initialState
@@ -73,12 +74,12 @@ initialState _ = { input: "", focused: false }
73
74
74handleAction :: Action -> H.HalogenM State Action () SearchFieldMessage Aff Unit
75handleAction :: Action -> H.HalogenM State Action () SearchFieldMessage Aff Unit
75handleAction = case _ of
76handleAction = case _ of
76−
77+ NoOp -> pure unit
77 InitKeyboardListener -> do
78 InitKeyboardListener -> do
78
79
79 document <- H.liftEffect $ Window.document =<< HTML.window
80 document <- H.liftEffect $ Window.document =<< HTML.window
80 H.subscribe' \sid ->
81 H.subscribe' \sid ->
81− ES.eventListenerEventSource
82+ ES.eventListener
82 KET.keyup
83 KET.keyup
83 (HTMLDocument.toEventTarget document)
84 (HTMLDocument.toEventTarget document)
84 (map (HandleKey sid) <<< KE.fromEvent)
85 (map (HandleKey sid) <<< KE.fromEvent)
@@ -155,15 +156,15 @@ render state =
155 [ HH.input
156 [ HH.input
156 [ HP.value state.input
157 [ HP.value state.input
157 , HP.placeholder "Search for definitions... (S to focus)"
158 , HP.placeholder "Search for definitions... (S to focus)"
158− , HP.id_ "docs-search-query-field"
159+ , HP.id "docs-search-query-field"
159 , HP.type_ HP.InputText
160 , HP.type_ HP.InputText
160 , HE.onKeyUp (\event ->
161 , HE.onKeyUp (\event ->
161 case KeyboardEvent.code event of
162 case KeyboardEvent.code event of
162− "Enter" -> Just EnterPressed
163+ "Enter" -> EnterPressed
163− _ -> Nothing)
164+ _ -> NoOp)
164− , HE.onValueInput (Just <<< InputAction)
165+ , HE.onValueInput InputAction
165− , HE.onFocusIn $ const $ Just $ FocusChanged true
166+ , HE.onFocusIn $ const $ FocusChanged true
166− , HE.onFocusOut $ const $ Just $ FocusChanged false
167+ , HE.onFocusOut $ const $ FocusChanged false
167 , HS.style do
168 , HS.style do
168
169
169 let pursuitColor = rgb 0x1d 0x22 0x2d
170 let pursuitColor = rgb 0x1d 0x22 0x2d
src/Docs/Search/App/SearchResults.purs+86−84
@@ -3,25 +3,27 @@ module Docs.Search.App.SearchResults where
3
3
4import Docs.Search.App.SearchField (SearchFieldMessage(..))
4import Docs.Search.App.SearchField (SearchFieldMessage(..))
5import Docs.Search.BrowserEngine (PartialIndex, browserSearchEngine)
5import Docs.Search.BrowserEngine (PartialIndex, browserSearchEngine)
6−import Docs.Search.Config (config)
6+import Docs.Search.Config as Config
7import Docs.Search.Declarations (DeclLevel(..), declLevelToHashAnchor)
7import Docs.Search.Declarations (DeclLevel(..), declLevelToHashAnchor)
8import Docs.Search.DocsJson (DataDeclType(..))
8import Docs.Search.DocsJson (DataDeclType(..))
9−import Docs.Search.Engine (Result(..))
9+import Docs.Search.Engine (Result(..), packageInfoToString)
10import Docs.Search.Engine as Engine
10import Docs.Search.Engine as Engine
11import Docs.Search.Extra (homePageFromRepository, (>#>))
11import Docs.Search.Extra (homePageFromRepository, (>#>))
12import Docs.Search.ModuleIndex (ModuleResult)
12import Docs.Search.ModuleIndex (ModuleResult)
13import Docs.Search.PackageIndex (PackageResult)
13import Docs.Search.PackageIndex (PackageResult)
14import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
14import 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)
16import Docs.Search.TypeIndex (TypeIndex)
16import Docs.Search.TypeIndex (TypeIndex)
17+import Docs.Search.Types (Identifier(..), ModuleName(..), PackageName)
18+import Docs.Search.Meta (Meta)
17
19
18import Prelude
20import Prelude
19−
21+import Prim hiding (Type, Constraint)
20import Data.Array ((!!))
22import Data.Array ((!!))
21import Data.Array as Array
23import Data.Array as Array
22import Data.List as List
24import Data.List as List
23import Data.Maybe (Maybe(..), isJust, fromMaybe)
25import Data.Maybe (Maybe(..), isJust, fromMaybe)
24−import Data.Newtype (wrap)
26+import Data.Newtype (wrap, unwrap)
25import Data.String.CodeUnits (stripSuffix) as String
27import Data.String.CodeUnits (stripSuffix) as String
26import Data.String.Common (null, trim) as String
28import Data.String.Common (null, trim) as String
27import Data.String.Pattern (Pattern(..)) as String
29import Data.String.Pattern (Pattern(..)) as String
@@ -55,6 +57,7 @@ type State = { engineState :: EngineState
55 , resultsCount :: Int
57 , resultsCount :: Int
56 , mode :: Mode
58 , mode :: Mode
57 , markdownIt :: MD.MarkdownIt
59 , markdownIt :: MD.MarkdownIt
60+ , localPackageName :: PackageName
58 }
61 }
59
62
60
63
@@ -63,7 +66,7 @@ data Query a
63
66
64
67
65data Action
68data Action
66− = SearchResultClicked String
69+ = SearchResultClicked ModuleName
67 | MoreResultsRequested
70 | MoreResultsRequested
68
71
69
72
@@ -72,16 +75,18 @@ mkComponent
72 . EngineState
75 . EngineState
73 -> Element
76 -> Element
74 -> MD.MarkdownIt
77 -> MD.MarkdownIt
78+ -> Meta
75− -> H.Component HH.HTML Query i o Aff
79+ -> H.Component Query i o Aff
76−mkComponent initialEngineState contents markdownIt =
80+mkComponent initialEngineState contents markdownIt { localPackageName } =
77 H.mkComponent
81 H.mkComponent
78 { initialState: const { engineState: initialEngineState
82 { initialState: const { engineState: initialEngineState
79 , results: []
83 , results: []
80 , input: ""
84 , input: ""
81 , contents
85 , contents
82− , resultsCount: config.resultsCount
86+ , resultsCount: Config.resultsCount
83 , mode: Off
87 , mode: Off
84 , markdownIt
88 , markdownIt
89+ , localPackageName
85 }
90 }
86 , render
91 , render
87 , eval: H.mkEval $ H.defaultEval { handleQuery = handleQuery
92 , eval: H.mkEval $ H.defaultEval { handleQuery = handleQuery
@@ -111,7 +116,7 @@ handleQuery (MessageFromSearchField (InputUpdated input_) next) = do
111 H.modify_ (_ { mode = Off })
116 H.modify_ (_ { mode = Off })
112 showPageContents
117 showPageContents
113 else do
118 else do
114− H.modify_ (_ { mode = Loading, resultsCount = config.resultsCount })
119+ H.modify_ (_ { mode = Loading, resultsCount = Config.resultsCount })
115
120
116 void $ H.fork do
121 void $ H.fork do
117 { index, results } <- H.liftAff $
122 { index, results } <- H.liftAff $
@@ -145,7 +150,7 @@ handleAction = case _ of
145 location <- Window.location window
150 location <- Window.location window
146 pathname <- Location.pathname location
151 pathname <- Location.pathname location
147 pure $ isJust $
152 pure $ isJust $
148− String.stripSuffix (String.Pattern $ moduleName <> ".html") pathname
153+ String.stripSuffix (String.Pattern $ unwrap moduleName <> ".html") pathname
149
154
150 when onThisPage do
155 when onThisPage do
151 showPageContents
156 showPageContents
@@ -190,18 +195,17 @@ render state@{ mode: Active, results: [] } =
190 , HH.text " did not yield any results."
195 , HH.text " did not yield any results."
191 ]
196 ]
192 ]
197 ]
193−
194render state@{ mode: Active } =
198render state@{ mode: Active } =
195 renderContainer $
199 renderContainer $
196 [ HH.h1_ [ HH.text "Search results" ]
200 [ HH.h1_ [ HH.text "Search results" ]
197
201
198 , HH.div_ $
202 , HH.div_ $
199− Array.concat $ shownResults <#> renderResult state.markdownIt
203+ Array.concat $ shownResults <#> renderResult state
200
204
201− , HH.div [ HP.class_ (wrap "load_more"), HP.id_ "load-more" ]
205+ , HH.div [ HP.class_ (wrap "load_more"), HP.id "load-more" ]
202 [ if Array.length shownResults < Array.length state.results
206 [ if Array.length shownResults < Array.length state.results
203− then HH.a [ HP.id_ "load-more-link"
207+ then HH.a [ HP.id "load-more-link"
204− , HE.onClick $ const $ Just MoreResultsRequested ]
208+ , HE.onClick $ const MoreResultsRequested ]
205 [ HH.text "Show more results" ]
209 [ HH.text "Show more results" ]
206 else HH.p_
210 else HH.p_
207 [ HH.text "No further results." ]
211 [ HH.text "No further results." ]
@@ -210,7 +214,6 @@ render state@{ mode: Active } =
210 where
214 where
211 shownResults = Array.take state.resultsCount state.results
215 shownResults = Array.take state.resultsCount state.results
212
216
213−
214renderContainer :: forall a b. Array (HH.HTML b a) -> HH.HTML b a
217renderContainer :: forall a b. Array (HH.HTML b a) -> HH.HTML b a
215renderContainer =
218renderContainer =
216 HH.div [ HP.classes [ wrap "container", wrap "clearfix" ] ] <<<
219 HH.div [ HP.classes [ wrap "container", wrap "clearfix" ] ] <<<
@@ -228,13 +231,17 @@ renderSummary text =
228
231
229renderResult
232renderResult
230 :: forall a
233 :: forall a
231− . MD.MarkdownIt
234+ . State
232 -> Result
235 -> Result
233 -> Array (HH.HTML a Action)
236 -> Array (HH.HTML a Action)
234−renderResult markdownIt (DeclResult r) = renderSearchResult markdownIt r
237+renderResult state (DeclResult r) =
238+ renderSearchResult state r
235−renderResult markdownIt (TypeResult r) = renderSearchResult markdownIt r
239+renderResult state (TypeResult r) =
240+ renderSearchResult state r
236−renderResult markdownIt (PackResult r) = renderPackageResult r
241+renderResult state (PackResult r) =
242+ renderPackageResult r
237−renderResult markdownIt (MdlResult r) = renderModuleResult r
243+renderResult state (MdlResult r) =
244+ renderModuleResult r
238
245
239
246
240renderPackageResult
247renderPackageResult
@@ -254,7 +261,7 @@ renderPackageResult { name, description, repository } =
254 , HH.a [ HP.class_ (wrap "result__link")
261 , HH.a [ HP.class_ (wrap "result__link")
255 , HP.href $ fromMaybe "" repository # homePageFromRepository
262 , HP.href $ fromMaybe "" repository # homePageFromRepository
256 ]
263 ]
257− [ HH.text name ]
264+ [ HH.text $ unwrap name ]
258 ]
265 ]
259 ]
266 ]
260 ] <>
267 ] <>
@@ -280,9 +287,9 @@ renderModuleResult { name, package } =
280 [ HH.text "M" ]
287 [ HH.text "M" ]
281
288
282 , HH.a [ HP.class_ (wrap "result__link")
289 , HH.a [ HP.class_ (wrap "result__link")
283− , HP.href $ name <> ".html"
290+ , HP.href $ unwrap name <> ".html"
284 ]
291 ]
285− [ HH.text name ]
292+ [ HH.text $ unwrap name ]
286 ]
293 ]
287 ]
294 ]
288 ]
295 ]
@@ -290,27 +297,27 @@ renderModuleResult { name, package } =
290
297
291renderSearchResult
298renderSearchResult
292 :: forall a
299 :: forall a
293− . MD.MarkdownIt
300+ . State
294 -> SearchResult
301 -> SearchResult
295 -> Array (HH.HTML a Action)
302 -> Array (HH.HTML a Action)
296−renderSearchResult markdownIt (SearchResult result) =
303+renderSearchResult state (SearchResult result) =
297 -- class names here and below are from Pursuit.
304 -- class names here and below are from Pursuit.
298 [ HH.div [ HP.class_ (wrap "result") ]
305 [ HH.div [ HP.class_ (wrap "result") ]
299 [ HH.h3 [ HP.class_ (wrap "result__title") ]
306 [ HH.h3 [ HP.class_ (wrap "result__title") ]
300 [ HH.a [ HP.class_ (wrap "result__link")
307 [ HH.a [ HP.class_ (wrap "result__link")
301− , HE.onClick $ const $ Just $ SearchResultClicked result.moduleName
308+ , HE.onClick $ const $ SearchResultClicked result.moduleName
302 , HP.href $
309 , HP.href $
303− result.moduleName <> ".html#" <>
310+ unwrap result.moduleName <> ".html#" <>
304− result.hashAnchor <> ":" <> result.name
311+ result.hashAnchor <> ":" <> unwrap result.name
305 ]
312 ]
306− [ HH.text result.name ]
313+ [ HH.text $ unwrap result.name ]
307 ]
314 ]
308 ]
315 ]
309
316
310 , HH.div [ HP.class_ (wrap "result__body") ] $
317 , HH.div [ HP.class_ (wrap "result__body") ] $
311 renderResultType result <>
318 renderResultType result <>
312
319
313− result.comments >#> pure <<< MDH.render_ markdownIt
320+ result.comments >#> pure <<< MDH.render_ state.markdownIt
314
321
315 , HH.div [ HP.class_ (wrap "result__actions") ]
322 , HH.div [ HP.class_ (wrap "result__actions") ]
316
323
@@ -321,7 +328,7 @@ renderSearchResult markdownIt (SearchResult result) =
321 , HP.title "Package"
328 , HP.title "Package"
322 ]
329 ]
323 [ HH.text "P" ]
330 [ HH.text "P" ]
324− , HH.text result.packageName
331+ , HH.text $ packageInfoToString state.localPackageName result.packageInfo
325 ]
332 ]
326
333
327 , HH.span [ HP.class_ (wrap "result__actions__item") ]
334 , HH.span [ HP.class_ (wrap "result__actions__item") ]
@@ -331,7 +338,7 @@ renderSearchResult markdownIt (SearchResult result) =
331 , HP.title "Module"
338 , HP.title "Module"
332 ]
339 ]
333 [ HH.text "M" ]
340 [ HH.text "M" ]
334− , HH.text result.moduleName
341+ , HH.text $ unwrap result.moduleName
335 ]
342 ]
336 ]
343 ]
337 ]
344 ]
@@ -340,8 +347,8 @@ renderSearchResult markdownIt (SearchResult result) =
340renderResultType
347renderResultType
341 :: forall a rest
348 :: forall a rest
342 . { info :: ResultInfo
349 . { info :: ResultInfo
343− , name :: String
350+ , name :: Identifier
344− , moduleName :: String
351+ , moduleName :: ModuleName
345 | rest
352 | rest
346 }
353 }
347 -> Array (HH.HTML a Action)
354 -> Array (HH.HTML a Action)
@@ -371,16 +378,16 @@ renderResultType result =
371
378
372renderValueSignature
379renderValueSignature
373 :: forall a rest
380 :: forall a rest
374− . { moduleName :: String
381+ . { moduleName :: ModuleName
375− , name :: String
382+ , name :: Identifier
376 | rest
383 | rest
377 }
384 }
378 -> Type
385 -> Type
379 -> Array (HH.HTML a Action)
386 -> Array (HH.HTML a Action)
380renderValueSignature result ty =
387renderValueSignature result ty =
381 [ HH.a [ makeHref ValueLevel false result.moduleName result.name
388 [ HH.a [ makeHref ValueLevel false result.moduleName result.name
382− , HE.onClick $ const $ Just $ SearchResultClicked result.moduleName ]
389+ , HE.onClick $ const $ SearchResultClicked result.moduleName ]
383− [ HH.text result.name ]
390+ [ HH.text $ unwrap result.name ]
384 , HH.text " :: "
391 , HH.text " :: "
385 , renderType ty ]
392 , renderType ty ]
386
393
@@ -391,7 +398,7 @@ renderTypeClassSignature
391 , arguments :: Array TypeArgument
398 , arguments :: Array TypeArgument
392 , superclasses :: Array Constraint
399 , superclasses :: Array Constraint
393 }
400 }
394− -> { name :: String, moduleName :: String | rest }
401+ -> { name :: Identifier, moduleName :: ModuleName | rest }
395 -> Array (HH.HTML a Action)
402 -> Array (HH.HTML a Action)
396renderTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName } =
403renderTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName } =
397 [ keyword "class"
404 [ keyword "class"
@@ -410,10 +417,10 @@ renderTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName
410 ]
417 ]
411 , space
418 , space
412 , HH.a [ makeHref TypeLevel false moduleName name
419 , HH.a [ makeHref TypeLevel false moduleName name
413− , HE.onClick $ const $ Just $
420+ , HE.onClick $ const $
414 SearchResultClicked moduleName
421 SearchResultClicked moduleName
415 ]
422 ]
416− [ HH.text name ]
423+ [ HH.text $ unwrap name ]
417 , space
424 , space
418 ] <> (
425 ] <> (
419 Array.intercalate [ space ] $
426 Array.intercalate [ space ] $
@@ -443,10 +450,10 @@ renderTypeClassMemberSignature
443 , typeClass :: QualifiedName
450 , typeClass :: QualifiedName
444 , typeClassArguments :: Array TypeArgument
451 , typeClassArguments :: Array TypeArgument
445 }
452 }
446− -> { name :: String | rest }
453+ -> { name :: Identifier | rest }
447 -> Array (HH.HTML a Action)
454 -> Array (HH.HTML a Action)
448renderTypeClassMemberSignature { type: ty, typeClass, typeClassArguments } result =
455renderTypeClassMemberSignature { type: ty, typeClass, typeClassArguments } result =
449− [ HH.text result.name
456+ [ HH.text $ unwrap result.name
450 , HH.text " :: "
457 , HH.text " :: "
451 , renderType ty
458 , renderType ty
452 ]
459 ]
@@ -456,7 +463,7 @@ renderDataSignature
456 :: forall a rest
463 :: forall a rest
457 . { typeArguments :: Array TypeArgument
464 . { typeArguments :: Array TypeArgument
458 , dataDeclType :: DataDeclType }
465 , dataDeclType :: DataDeclType }
459− -> { name :: String | rest }
466+ -> { name :: Identifier | rest }
460 -> Array (HH.HTML a Action)
467 -> Array (HH.HTML a Action)
461renderDataSignature { typeArguments, dataDeclType } { name } =
468renderDataSignature { typeArguments, dataDeclType } { name } =
462 [ keyword
469 [ keyword
@@ -464,7 +471,7 @@ renderDataSignature { typeArguments, dataDeclType } { name } =
464 NewtypeDataDecl -> "newtype"
471 NewtypeDataDecl -> "newtype"
465 DataDataDecl -> "data"
472 DataDataDecl -> "data"
466 , space
473 , space
467− , HH.text name
474+ , HH.text $ unwrap name
468 , space
475 , space
469 , HH.span_ $
476 , HH.span_ $
470 Array.intercalate [ space ] $
477 Array.intercalate [ space ] $
@@ -477,12 +484,12 @@ renderTypeSynonymSignature
477 . { type :: Type
484 . { type :: Type
478 , arguments :: Array TypeArgument
485 , arguments :: Array TypeArgument
479 }
486 }
480− -> { name :: String | rest }
487+ -> { name :: Identifier | rest }
481 -> Array (HH.HTML a Action)
488 -> Array (HH.HTML a Action)
482renderTypeSynonymSignature { type: ty, arguments } { name } =
489renderTypeSynonymSignature { type: ty, arguments } { name } =
483 [ keyword "type"
490 [ keyword "type"
484 , space
491 , space
485− , HH.text name
492+ , HH.text $ unwrap name
486 , space
493 , space
487 , HH.span_ $
494 , HH.span_ $
488 Array.intercalate [ space ] $
495 Array.intercalate [ space ] $
@@ -498,12 +505,12 @@ renderTypeArgument :: forall a. TypeArgument -> Array (HH.HTML a Action)
498renderTypeArgument (TypeArgument { name, mbKind }) =
505renderTypeArgument (TypeArgument { name, mbKind }) =
499 case mbKind of
506 case mbKind of
500 Nothing ->
507 Nothing ->
501− [ HH.text name ]
508+ [ HH.text $ name ]
502 Just kind ->
509 Just kind ->
503 [ HH.text "("
510 [ HH.text "("
504− , HH.text name
511+ , HH.text $ name
505 , HH.text " :: "
512 , HH.text " :: "
506− , renderKind kind
513+ , renderType kind
507 , HH.text ")"
514 , HH.text ")"
508 ]
515 ]
509
516
@@ -520,15 +527,15 @@ renderType = case _ of
520 TypeOp qname -> renderQualifiedName true TypeLevel qname
527 TypeOp qname -> renderQualifiedName true TypeLevel qname
521
528
522 TypeApp (TypeApp (TypeConstructor
529 TypeApp (TypeApp (TypeConstructor
523− (QualifiedName { moduleName: [ "Prim" ]
530+ (QualifiedName { moduleNameParts: [ "Prim" ]
524− , name: "Function" })) t1) t2 ->
531+ , name: Identifier "Function" })) t1) t2 ->
525 HH.span_ [ renderType t1
532 HH.span_ [ renderType t1
526 , syntax " -> "
533 , syntax " -> "
527 , renderType t2
534 , renderType t2
528 ]
535 ]
529
536
530− TypeApp (TypeConstructor (QualifiedName { moduleName: [ "Prim" ]
537+ TypeApp (TypeConstructor (QualifiedName { moduleNameParts: [ "Prim" ]
531− , name: "Record" }))
538+ , name: Identifier "Record" }))
532 row ->
539 row ->
533 renderRow false row
540 renderRow false row
534
541
@@ -538,6 +545,9 @@ renderType = case _ of
538 , renderType t2
545 , renderType t2
539 ]
546 ]
540
547
548+ KindApp t1 t2 ->
549+ HH.span_ [ renderType t1, space, renderType t2 ]
550+
541 ty@(ForAll _ _ _) ->
551 ty@(ForAll _ _ _) ->
542 renderForAll ty
552 renderForAll ty
543
553
@@ -551,6 +561,9 @@ renderType = case _ of
551 ty@REmpty -> renderRow true ty
561 ty@REmpty -> renderRow true ty
552 ty@(RCons _ _ _) -> renderRow true ty
562 ty@(RCons _ _ _) -> renderRow true ty
553
563
564+ Kinded t1 t2 ->
565+ HH.span_ [ renderType t1, space, syntax "::", space, renderType t2 ]
566+
554 BinaryNoParensType op t1 t2 ->
567 BinaryNoParensType op t1 t2 ->
555 HH.span_
568 HH.span_
556 [ renderType t1
569 [ renderType t1
@@ -585,7 +598,7 @@ renderForAll ty =
585 HH.span_ [ HH.text $ " (" <> name <> " "
598 HH.span_ [ HH.text $ " (" <> name <> " "
586 , syntax "::"
599 , syntax "::"
587 , space
600 , space
588− , renderKind kind
601+ , renderType kind
589 , HH.text ")" ]
602 , HH.text ")" ]
590 ) <>
603 ) <>
591
604
@@ -623,7 +636,7 @@ renderRow asRow =
623
636
624 ( Array.intercalate [ HH.text ", " ] $ Array.fromFoldable $ rows <#>
637 ( Array.intercalate [ HH.text ", " ] $ Array.fromFoldable $ rows <#>
625 \entry ->
638 \entry ->
626− [ HH.span_ [ HH.text $ entry.row <> " :: "
639+ [ HH.span_ [ HH.text $ unwrap entry.row <> " :: "
627 , renderType entry.ty ] ]
640 , renderType entry.ty ] ]
628 ) <>
641 ) <>
629
642
@@ -635,6 +648,9 @@ renderRow asRow =
635 opening = if asRow then "( " else "{ "
648 opening = if asRow then "( " else "{ "
636 closing = if asRow then " )" else " }"
649 closing = if asRow then " )" else " }"
637
650
651+ primRecord :: QualifiedName
652+ primRecord = QualifiedName { moduleNameParts: [ "Prim" ], name: Identifier "Record" }
653+
638
654
639renderConstraint
655renderConstraint
640 :: forall a
656 :: forall a
@@ -652,28 +668,18 @@ renderQualifiedName
652 -> DeclLevel
668 -> DeclLevel
653 -> QualifiedName
669 -> QualifiedName
654 -> HH.HTML a Action
670 -> HH.HTML a Action
655−renderQualifiedName isInfix level (QualifiedName { moduleName, name })
671+renderQualifiedName isInfix level (QualifiedName { moduleNameParts, name })
656 = if isBuiltIn then
672 = if isBuiltIn then
657− HH.text name
673+ HH.text $ unwrap name
658 else
674 else
659− HH.a [ HE.onClick $ const $ Just $
675+ HH.a [ HE.onClick $ const $
660− SearchResultClicked moduleNameString
676+ SearchResultClicked $ moduleName
661− , makeHref level isInfix moduleNameString name
677+ , makeHref level isInfix moduleName name
662 ]
678 ]
663− [ HH.text name ]
679+ [ HH.text $ unwrap name ]
664 where
680 where
665− moduleNameString = Array.intercalate "." moduleName
681+ moduleName = ModuleName $ Array.intercalate "." $ moduleNameParts
666− isBuiltIn = moduleName !! 0 == Just "Prim"
682+ isBuiltIn = moduleNameParts !! 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
677
683
678
684
679-- | Construct a `href` property value w.r.t. `DeclLevel`.
685-- | Construct a `href` property value w.r.t. `DeclLevel`.
@@ -681,18 +687,14 @@ makeHref
681 :: forall t rest
687 :: forall t rest
682 . DeclLevel
688 . DeclLevel
683 -> Boolean
689 -> Boolean
684− -> String
690+ -> ModuleName
685− -> String
691+ -> Identifier
686 -> HH.IProp ( href :: String | rest ) t
692 -> HH.IProp ( href :: String | rest ) t
687makeHref level isInfix moduleName name =
693makeHref level isInfix moduleName name =
688 HP.href $
694 HP.href $
689− moduleName <> ".html#" <>
695+ unwrap moduleName <> ".html#" <>
690 declLevelToHashAnchor level <> ":" <>
696 declLevelToHashAnchor level <> ":" <>
691− if isInfix then "type (" <> name <> ")" else name
697+ if isInfix then "type (" <> unwrap name <> ")" else unwrap name
692−
693−
694−primRecord :: QualifiedName
695−primRecord = QualifiedName { moduleName: [ "Prim" ], name: "Record" }
696
698
697
699
698keyword
700keyword
src/Docs/Search/App/Sidebar.purs+79−31
@@ -1,21 +1,22 @@
1module Docs.Search.App.Sidebar where
1module Docs.Search.App.Sidebar where
2
2
3−import Docs.Search.Config (config)
3+import Docs.Search.Config as Config
4+import Docs.Search.Meta (Meta)
4−import Docs.Search.ModuleIndex (PackedModuleIndex)
5+import Docs.Search.ModuleIndex (ModuleIndex)
5−import Docs.Search.Types (ModuleName, PackageName)
6+import Docs.Search.Types (ModuleName(..), PackageInfo(..), PackageName)
6
7
7import Prelude
8import Prelude
9+
8import Data.Array as Array
10import Data.Array as Array
9import Data.Lens ((.~))
11import Data.Lens ((.~))
10import Data.Lens.Record (prop)
12import Data.Lens.Record (prop)
11import Data.List (foldr)
13import Data.List (foldr)
12import Data.Map (Map)
14import Data.Map (Map)
13import Data.Map as Map
15import Data.Map as Map
14−import Data.Maybe (Maybe(..), isJust)
16+import Data.Maybe (Maybe(..), isJust, fromMaybe)
15−import Data.Newtype (wrap)
17+import Data.Newtype (wrap, unwrap)
16import Data.Set (Set)
18import Data.Set (Set)
17import Data.Set as Set
19import Data.Set as Set
18−import Data.Symbol (SProxy(..))
19import Data.Tuple.Nested (type (/\), (/\))
20import Data.Tuple.Nested (type (/\), (/\))
20import Effect (Effect)
21import Effect (Effect)
21import Effect.Aff (Aff)
22import Effect.Aff (Aff)
@@ -23,9 +24,16 @@ import Halogen as H
23import Halogen.HTML as HH
24import Halogen.HTML as HH
24import Halogen.HTML.Events as HE
25import Halogen.HTML.Events as HE
25import Halogen.HTML.Properties as HP
26import Halogen.HTML.Properties as HP
27+import Type.Proxy (Proxy(..))
26import Web.HTML as HTML
28import Web.HTML as HTML
27import Web.HTML.Window as Window
29import Web.HTML.Window as Window
28import Web.Storage.Storage as Storage
30import 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
29
37
30
38
31data Action = ToggleGrouping GroupingMode
39data Action = ToggleGrouping GroupingMode
@@ -42,26 +50,33 @@ data IsIndexHTML = IsIndexHTML | NotIndexHTML
42
50
43derive instance isIndexHTMLEq :: Eq IsIndexHTML
51derive instance isIndexHTMLEq :: Eq IsIndexHTML
44
52
45−type State = { moduleIndex :: Map PackageName (Set ModuleName)
53+type State = { packageModules :: Map PackageInfo (Set ModuleName)
46 , groupingMode :: GroupingMode
54 , groupingMode :: GroupingMode
47 , moduleNames :: Array ModuleName
55 , moduleNames :: Array ModuleName
48 , isIndexHTML :: IsIndexHTML
56 , isIndexHTML :: IsIndexHTML
57+ , localPackageName :: PackageName
58+ , currentPackage :: PackageInfo
49 }
59 }
50
60
51
61
52mkComponent
62mkComponent
53 :: forall i
63 :: forall i
54− . PackedModuleIndex
64+ . ModuleIndex
55 -> IsIndexHTML
65 -> IsIndexHTML
66+ -> Meta
56− -> Aff (H.Component HH.HTML Query i Action Aff)
67+ -> Aff (H.Component Query i Action Aff)
57−mkComponent moduleIndex isIndexHTML = do
68+mkComponent moduleIndex@{ packageModules } isIndexHTML { localPackageName } = do
58 groupingMode <- H.liftEffect loadGroupingModeFromLocalStorage
69 groupingMode <- H.liftEffect loadGroupingModeFromLocalStorage
70+ mbModuleName <- H.liftEffect getCurrentModuleName
71+ let currentPackage = getCurrentPackage moduleIndex mbModuleName
59 pure $
72 pure $
60 H.mkComponent
73 H.mkComponent
61− { initialState: const { moduleIndex
74+ { initialState: const { packageModules
62 , groupingMode
75 , groupingMode
63 , moduleNames
76 , moduleNames
64 , isIndexHTML
77 , isIndexHTML
78+ , localPackageName
79+ , currentPackage
65 }
80 }
66 , render
81 , render
67 , eval: H.mkEval $ H.defaultEval { handleAction = handleAction
82 , eval: H.mkEval $ H.defaultEval { handleAction = handleAction
@@ -69,7 +84,9 @@ mkComponent moduleIndex isIndexHTML = do
69 }
84 }
70 }
85 }
71 where
86 where
87+ moduleNames =
72− moduleNames = Array.sort $ Array.fromFoldable $ foldr Set.union mempty moduleIndex
88+ Array.sort $ Array.fromFoldable $
89+ foldr Set.union mempty moduleIndex.packageModules
73
90
74
91
75handleAction
92handleAction
@@ -83,9 +100,9 @@ handleAction (ToggleGrouping groupingMode) = do
83 window <- HTML.window
100 window <- HTML.window
84 localStorage <- Window.localStorage window
101 localStorage <- Window.localStorage window
85
102
86− if groupingMode == GroupByPackage
103+ if groupingMode == DontGroup
87− then Storage.setItem config.groupModulesItem "true" localStorage
104+ then Storage.setItem Config.groupModulesItem "false" localStorage
88− else Storage.removeItem config.groupModulesItem localStorage
105+ else Storage.removeItem Config.groupModulesItem localStorage
89
106
90
107
91handleQuery
108handleQuery
@@ -104,25 +121,25 @@ render
104 :: forall m
121 :: forall m
105 . State
122 . State
106 -> H.ComponentHTML Action () m
123 -> H.ComponentHTML Action () m
107−render { moduleIndex, groupingMode, moduleNames, isIndexHTML } =
124+render state@{ groupingMode, moduleNames, localPackageName } =
108
125
109 HH.div [ HP.classes [ wrap "col"
126 HH.div [ HP.classes [ wrap "col"
110− , wrap $ if isIndexHTML == IsIndexHTML
127+ , wrap $ if state.isIndexHTML == IsIndexHTML
111 then "col--main"
128 then "col--main"
112 else "col--aside"
129 else "col--aside"
113 ]
130 ]
114 ]
131 ]
115
132
116− [ HH.h3_ [ HH.text "Modules" ]
133+ [ HH.h3_ [ HH.text $ if groupingMode == DontGroup then "Modules" else "Packages" ]
117− , HH.input [ HP.id_ "group-modules__input"
134+ , HH.input [ HP.id "group-modules__input"
118 , HP.type_ HP.InputCheckbox
135 , HP.type_ HP.InputCheckbox
119 , HP.checked (groupingMode == GroupByPackage)
136 , HP.checked (groupingMode == GroupByPackage)
120− , HE.onChecked $ Just <<< ToggleGrouping <<< isCheckedToGroupingMode
137+ , HE.onChecked $ ToggleGrouping <<< isCheckedToGroupingMode
121 ]
138 ]
122
139
123 , HH.text " "
140 , HH.text " "
124 , HH.label [ HP.for "group-modules__input"
141 , HH.label [ HP.for "group-modules__input"
125− , HP.id_ "group-modules__label"
142+ , HP.id "group-modules__label"
126 ]
143 ]
127 [ HH.text " GROUP BY PACKAGE" ]
144 [ HH.text " GROUP BY PACKAGE" ]
128
145
@@ -132,22 +149,37 @@ render { moduleIndex, groupingMode, moduleNames, isIndexHTML } =
132 ]
149 ]
133 where
150 where
134
151
135− renderPackageEntry (packageName /\ modules) =
152+ renderPackageEntry (package /\ modules) =
136 HH.li [ HP.classes [ wrap "li-package" ] ]
153 HH.li [ HP.classes [ wrap "li-package" ] ]
137− [ HH.details_
154+ [ HH.details
155+ (if isCurrentPackage then [ HP.attr (wrap "open") "" ] else [])
138− [ HH.summary_ [ HH.text packageName ]
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+ ]
139 , HH.ul_ $ Set.toUnfoldable modules <#> renderModuleName
164 , HH.ul_ $ Set.toUnfoldable modules <#> renderModuleName
140 ]
165 ]
141 ]
166 ]
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
142
174
143 renderModuleName moduleName =
175 renderModuleName moduleName =
144 HH.li_
176 HH.li_
145− [ HH.a [ HP.href (moduleName <> ".html") ]
177+ [ HH.a [ HP.href (unwrap moduleName <> ".html") ]
146− [ HH.text moduleName ]
178+ [ HH.text $ unwrap moduleName ]
147 ]
179 ]
148
180
149− packageList :: Array (String /\ Set ModuleName)
181+ packageList :: Array (PackageInfo /\ Set ModuleName)
150− packageList = Map.toUnfoldable moduleIndex
182+ packageList = Map.toUnfoldable state.packageModules
151
183
152
184
153-- | Decide whether to group modules by package in the sidebar, using localStorage.
185-- | Decide whether to group modules by package in the sidebar, using localStorage.
@@ -155,8 +187,24 @@ loadGroupingModeFromLocalStorage :: Effect GroupingMode
155loadGroupingModeFromLocalStorage = do
187loadGroupingModeFromLocalStorage = do
156 window <- HTML.window
188 window <- HTML.window
157 localStorage <- Window.localStorage window
189 localStorage <- Window.localStorage window
158− mbGroupModules <- Storage.getItem config.groupModulesItem localStorage
190+ mbDontGroupModules <- Storage.getItem Config.groupModulesItem localStorage
159− pure $ if isJust mbGroupModules then GroupByPackage else DontGroup
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
160
208
161
209
162-- | Convert checkbox status to sidebar mode
210-- | Convert checkbox status to sidebar mode
@@ -167,4 +215,4 @@ isCheckedToGroupingMode = if _ then GroupByPackage else DontGroup
167-- Some optics:
215-- Some optics:
168
216
169_groupingMode :: forall a b rest. (a -> b) -> { groupingMode :: a | rest } -> { groupingMode :: b | rest }
217_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 @@
1/* global exports */
1/* global exports */
2
2
3−exports.loadIndex_ = function (partId) {
3+export function loadIndex_ (partId) {
4 return function (url) {
4 return function (url) {
5 return function () {
5 return function () {
6 return new Promise(function(resolve, reject) {
6 return new Promise(function(resolve, reject) {
src/Docs/Search/BrowserEngine.purs+10−14
@@ -1,12 +1,13 @@
1-- | A search engine that is used in the browser.
1-- | A search engine that is used in the browser.
2module Docs.Search.BrowserEngine where
2module Docs.Search.BrowserEngine where
3
3
4−import Docs.Search.Config (config)
4+import Docs.Search.Config as Config
5import Docs.Search.PackageIndex (queryPackageIndex)
5import Docs.Search.PackageIndex (queryPackageIndex)
6import Docs.Search.Engine (Engine, EngineState, Index)
6import Docs.Search.Engine (Engine, EngineState, Index)
7import Docs.Search.SearchResult (SearchResult)
7import Docs.Search.SearchResult (SearchResult)
8import Docs.Search.TypeIndex (TypeIndex)
8import Docs.Search.TypeIndex (TypeIndex)
9import Docs.Search.TypeIndex as TypeIndex
9import Docs.Search.TypeIndex as TypeIndex
10+import Docs.Search.Types (PartId(..), URL)
10import Docs.Search.ModuleIndex as ModuleIndex
11import Docs.Search.ModuleIndex as ModuleIndex
11
12
12import Prelude
13import Prelude
@@ -32,12 +33,9 @@ import Effect.Aff (Aff, try)
32
33
33
34
34newtype PartialIndex
35newtype PartialIndex
35− = PartialIndex (Map Int Index)
36+ = PartialIndex (Map PartId Index)
36
37
37derive instance newtypePartialIndex :: Newtype PartialIndex _
38derive instance newtypePartialIndex :: Newtype PartialIndex _
38−derive newtype instance semigroupPartialIndex :: Semigroup PartialIndex
39−derive newtype instance monoidPartialIndex :: Monoid PartialIndex
40−
41
39
42type BrowserEngineState = EngineState PartialIndex TypeIndex
40type BrowserEngineState = EngineState PartialIndex TypeIndex
43
41
@@ -52,13 +50,11 @@ query
52 -> Aff { index :: PartialIndex, results :: Array SearchResult }
50 -> Aff { index :: PartialIndex, results :: Array SearchResult }
53query index@(PartialIndex indexMap) input = do
51query index@(PartialIndex indexMap) input = do
54 let
52 let
55− path :: List Char
56 path =
53 path =
57 List.fromFoldable $
54 List.fromFoldable $
58 String.toCharArray $
55 String.toCharArray $
59 input
56 input
60
57
61− partId :: Int
62 partId = getPartId path
58 partId = getPartId path
63
59
64 case Map.lookup partId indexMap of
60 case Map.lookup partId indexMap of
@@ -68,7 +64,7 @@ query index@(PartialIndex indexMap) input = do
68
64
69
65
70 eiPartJson <-
66 eiPartJson <-
71− try $ toAffE $ loadIndex_ partId $ config.mkIndexPartLoadPath partId
67+ try $ toAffE $ loadIndex_ partId $ Config.mkIndexPartLoadPath partId
72
68
73 let
69 let
74 mbNewTrie :: Maybe (Trie Char (List SearchResult))
70 mbNewTrie :: Maybe (Trie Char (List SearchResult))
@@ -119,16 +115,16 @@ browserSearchEngine =
119
115
120
116
121-- | Find in which part of the index this path can be found.
117-- | Find in which part of the index this path can be found.
122−getPartId :: List Char -> Int
118+getPartId :: List Char -> PartId
123getPartId (a : b : _) =
119getPartId (a : b : _) =
124− (Char.toCharCode a + Char.toCharCode b) `mod` config.numberOfIndexParts
120+ PartId $ (Char.toCharCode a + Char.toCharCode b) `mod` Config.numberOfIndexParts
125getPartId (a : _) =
121getPartId (a : _) =
126− Char.toCharCode a `mod` config.numberOfIndexParts
122+ PartId $ Char.toCharCode a `mod` Config.numberOfIndexParts
127−getPartId _ = 0
123+getPartId _ = PartId 0
128
124
129
125
130-- | Load a part of the index by injecting a <script> tag into the DOM.
126-- | Load a part of the index by injecting a <script> tag into the DOM.
131foreign import loadIndex_
127foreign import loadIndex_
132− :: Int
128+ :: PartId
133− -> String
129+ -> URL
134 -> Effect (Promise Json)
130 -> Effect (Promise Json)
src/Docs/Search/Config.purs+79−66
@@ -1,72 +1,85 @@
1module Docs.Search.Config where
1module Docs.Search.Config where
2
2
3+import Docs.Search.Types (GlobalIdentifier, PackageName, PartId, URL, FilePath)
4+
3import Prelude
5import Prelude
4
6
5−-- | Some magic constants.
7+import Data.Newtype (wrap)
6−config ::
8+
7− { version :: String
9+version :: String
8− , declIndexDirectory :: String
10+version = "0.0.12"
9− , mkIndexPartLoadPath :: Int -> String
11+
10− , mkIndexPartPath :: Int -> String
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+
11− , moduleIndexPath :: String
25+moduleIndexPath :: FilePath
26+moduleIndexPath = wrap "generated-docs/html/index/modules.js"
27+
28+-- | Used to load mode index to the browser scope.
12− , moduleIndexLoadPath :: String
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.
13− , groupModulesItem :: String
45+groupModulesItem :: String
46+groupModulesItem = "PureScriptDocsSearchGroupModules"
47+
14− , packageInfoPath :: String
48+packageInfoPath :: FilePath
15− , packageInfoLoadPath :: String
49+packageInfoPath = wrap "generated-docs/html/index/packages.js"
16− , mkShapeScriptPath :: String -> String
50+
17− , numberOfIndexParts :: Int
51+packageInfoItem :: GlobalIdentifier
18− , outputDirectory :: String
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 ::
19− , penalties :: { excessiveConstraint :: Int
64+ { excessiveConstraint :: Int
20− , generalize :: Int
65+ , generalize :: Int
21− , instantiate :: Int
66+ , instantiate :: Int
22− , match :: Int
67+ , match :: Int
23− , matchConstraint :: Int
68+ , matchConstraint :: Int
24− , missingConstraint :: Int
69+ , missingConstraint :: Int
25− , rowsMismatch :: Int
70+ , rowsMismatch :: Int
26− , typeVars :: Int
71+ , typeVars :: Int
27− }
28− , requiredDirectories :: Array String
29− , resultsCount :: Int
30− , typeIndexDirectory :: String
31 }
72 }
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
73+penalties =
74+ { typeVars: 2
62− , match: 2
75+ , match: 2
63− , matchConstraint: 1
76+ , matchConstraint: 1
64− , instantiate: 2
77+ , instantiate: 2
65− , generalize: 2
78+ , generalize: 2
66− , rowsMismatch: 3
79+ , rowsMismatch: 3
67− , missingConstraint: 1
80+ , missingConstraint: 1
68− , excessiveConstraint: 1
81+ , excessiveConstraint: 1
69− }
70− -- ^ Penalties used to determine how "far" a type query is from a given type.
71− -- See Docs.Search.TypeQuery
72 }
82 }
83+
84+defaultPackageName :: PackageName
85+defaultPackageName = wrap "<local package>"
src/Docs/Search/Declarations.purs+77−48
@@ -1,20 +1,19 @@
1module Docs.Search.Declarations where
1module Docs.Search.Declarations where
2
2
3import Docs.Search.DocsJson (ChildDeclType(..), ChildDeclaration(..), DeclType(..), Declaration(..), DocsJson(..), SourceSpan)
3import Docs.Search.DocsJson (ChildDeclType(..), ChildDeclaration(..), DeclType(..), Declaration(..), DocsJson(..), SourceSpan)
4−import Docs.Search.Score (Scores)
4+import Docs.Search.Score (Scores, getPackageScore, getPackageScoreForPackageName)
5import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
5import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
6−import Docs.Search.TypeDecoder (Constraint(..), QualifiedName(..), Type(..), Kind, joinForAlls)
6+import Docs.Search.TypeDecoder (Constraint(..), QualifiedName(..), Type(..), joinForAlls)
7−import Docs.Search.Types (ModuleName, PackageName)
7+import Docs.Search.Types (ModuleName(..), PackageName(..), PackageInfo(..), Identifier(..))
8
8
9import Prelude
9import Prelude
10−
10+import Prim hiding (Type)
11import Control.Alt ((<|>))
11import Control.Alt ((<|>))
12import Data.Array ((!!))
12import Data.Array ((!!))
13import Data.Array as Array
13import Data.Array as Array
14−import Data.Foldable (foldr)
14+import Data.Foldable (foldl, foldr)
15import Data.List (List, (:))
15import Data.List (List, (:))
16import Data.List as List
16import Data.List as List
17−import Data.Map as Map
18import Data.Maybe (Maybe(..), fromMaybe)
17import Data.Maybe (Maybe(..), fromMaybe)
19import Data.Newtype (class Newtype, unwrap, wrap)
18import Data.Newtype (class Newtype, unwrap, wrap)
20import Data.Search.Trie (Trie, alter)
19import Data.Search.Trie (Trie, alter)
@@ -24,8 +23,7 @@ import Data.String.Common (toLower)
24import Data.String.Pattern (Pattern(..))
23import Data.String.Pattern (Pattern(..))
25
24
26
25
27−newtype Declarations
28− = Declarations (Trie Char (List SearchResult))
26+newtype Declarations = Declarations (Trie Char (List SearchResult))
29
27
30derive instance newtypeDeclarations :: Newtype Declarations _
28derive instance newtypeDeclarations :: Newtype Declarations _
31derive newtype instance semigroupDeclarations :: Semigroup Declarations
29derive newtype instance semigroupDeclarations :: Semigroup Declarations
@@ -42,7 +40,7 @@ insertDocsJson
42 -> Trie Char (List SearchResult)
40 -> Trie Char (List SearchResult)
43 -> Trie Char (List SearchResult)
41 -> Trie Char (List SearchResult)
44insertDocsJson scores (DocsJson { name, declarations }) trie
42insertDocsJson scores (DocsJson { name, declarations }) trie
45− = foldr (insertDeclaration scores name) trie declarations
43+ = foldr (insertDeclaration scores $ ModuleName name) trie declarations
46
44
47
45
48insertDeclaration
46insertDeclaration
@@ -63,13 +61,13 @@ insertSearchResult
63 -> Trie Char (List SearchResult)
61 -> Trie Char (List SearchResult)
64insertSearchResult { path, result } trie =
62insertSearchResult { path, result } trie =
65 let path' = List.fromFoldable $ toCharArray $ toLower path in
63 let path' = List.fromFoldable $ toCharArray $ toLower path in
66− alter path' (Just <<< updateResults) trie
64+ alter path' (Just <<< updateResults) trie
67− where
65+ where
68− updateResults mbOldResults
66+ updateResults mbOldResults
69− | Just oldResults <- mbOldResults =
67+ | Just oldResults <- mbOldResults =
70− result : oldResults
68+ result : oldResults
71− | otherwise =
69+ | otherwise =
72− List.singleton result
70+ List.singleton result
73
71
74
72
75-- | For each declaration, extract its own `SearchResult` and `SearchResult`s
73-- | For each declaration, extract its own `SearchResult` and `SearchResult`s
@@ -82,19 +80,17 @@ resultsForDeclaration
82 , result :: SearchResult
80 , result :: SearchResult
83 }
81 }
84resultsForDeclaration scores moduleName indexEntry@(Declaration entry) =
82resultsForDeclaration 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
83+ case mkInfo declLevel indexEntry of
89− Nothing -> mempty
84+ Nothing -> mempty
90− Just info' ->
85+ Just info' ->
91− let result = SearchResult { name: title
86+ let result = SearchResult { name: Identifier title
92 , comments
87 , comments
93 , hashAnchor: declLevelToHashAnchor declLevel
88 , hashAnchor: declLevelToHashAnchor declLevel
94 , moduleName
89 , moduleName
95 , sourceSpan
90 , sourceSpan
96− , packageName
91+ , packageInfo
97− , score: fromMaybe 0 $ Map.lookup packageName scores
92+ , score:
93+ fromMaybe zero $ getPackageScoreForPackageName scores <$> mbPackageName
98 , info: info'
94 , info: info'
99 }
95 }
100 in
96 in
@@ -104,8 +100,16 @@ resultsForDeclaration scores moduleName indexEntry@(Declaration entry) =
104 }
100 }
105 ) <>
101 ) <>
106 ( List.fromFoldable children >>=
102 ( List.fromFoldable children >>=
107− resultsForChildDeclaration scores packageName moduleName result
103+ resultsForChildDeclaration scores packageInfo moduleName result
108 )
104 )
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
109
113
110
114
111mkInfo :: DeclLevel -> Declaration -> Maybe ResultInfo
115mkInfo :: DeclLevel -> Declaration -> Maybe ResultInfo
@@ -188,35 +192,34 @@ getLevelAndName DeclExternKind name = { name, declLevel: KindLevel }
188-- | Extract package name from `sourceSpan.name`, which contains path to
192-- | Extract package name from `sourceSpan.name`, which contains path to
189-- | the source file. If `ModuleName` string starts with `Prim.`, it's a
193-- | the source file. If `ModuleName` string starts with `Prim.`, it's a
190-- | built-in (guaranteed by the compiler).
194-- | built-in (guaranteed by the compiler).
191−extractPackageName :: ModuleName -> Maybe SourceSpan -> PackageName
195+extractPackageName :: ModuleName -> Maybe SourceSpan -> PackageInfo
192−extractPackageName moduleName _
196+extractPackageName (ModuleName moduleName) _
193− | String.split (Pattern ".") moduleName !! 0 == Just "Prim" = "<builtin>"
197+ | String.split (Pattern ".") moduleName !! 0 == Just "Prim" = Builtin
194−extractPackageName _ Nothing = "<unknown>"
198+extractPackageName _ Nothing = UnknownPackage
195extractPackageName _ (Just { name }) =
199extractPackageName _ (Just { name }) =
196− let dirs = String.split (Pattern "/") name
197− in
198− fromMaybe "<local package>" do
200+ fromMaybe LocalPackage do
199− topLevelDir <- dirs !! 0
201+ topLevelDir <- dirs !! 0
200− if topLevelDir == ".spago"
202+ if topLevelDir == ".spago"
201− then dirs !! 1
203+ then Package <<< PackageName <$> dirs !! 1
202− else do
204+ else do
203− bowerDirIx <- Array.findIndex (_ == "bower_components") dirs
205+ bowerDirIx <- Array.findIndex (_ == "bower_components") dirs
204− dirs !! (bowerDirIx + 1)
206+ Package <<< PackageName <$> dirs !! (bowerDirIx + 1)
207+ where dirs = String.split (Pattern "/") name
205
208
206
209
207-- | Extract `SearchResults` from a `ChildDeclaration`.
210-- | Extract `SearchResults` from a `ChildDeclaration`.
208resultsForChildDeclaration
211resultsForChildDeclaration
209 :: Scores
212 :: Scores
210− -> PackageName
213+ -> PackageInfo
211 -> ModuleName
214 -> ModuleName
212 -> SearchResult
215 -> SearchResult
213 -> ChildDeclaration
216 -> ChildDeclaration
214 -> List { path :: String, result :: SearchResult }
217 -> List { path :: String, result :: SearchResult }
215−resultsForChildDeclaration scores packageName moduleName parentResult
218+resultsForChildDeclaration scores packageInfo moduleName parentResult
216 child@(ChildDeclaration { title, info, comments, mbSourceSpan })
219 child@(ChildDeclaration { title, info, comments, mbSourceSpan })
217 | Just resultInfo <- mkChildInfo parentResult child =
220 | Just resultInfo <- mkChildInfo parentResult child =
218 { path: title
221 { path: title
219− , result: SearchResult { name: title
222+ , result: SearchResult { name: Identifier title
220 , comments
223 , comments
221 -- `ChildDeclaration`s are always either data
224 -- `ChildDeclaration`s are always either data
222 -- constructors, type class members or instances.
225 -- constructors, type class members or instances.
@@ -225,8 +228,8 @@ resultsForChildDeclaration scores packageName moduleName parentResult
225 , hashAnchor: "v"
228 , hashAnchor: "v"
226 , moduleName
229 , moduleName
227 , sourceSpan: mbSourceSpan
230 , sourceSpan: mbSourceSpan
228− , packageName
231+ , packageInfo
229− , score: fromMaybe 0 $ Map.lookup packageName scores
232+ , score: getPackageScore scores packageInfo
230 , info: resultInfo
233 , info: resultInfo
231 }
234 }
232 } # List.singleton
235 } # List.singleton
@@ -241,8 +244,33 @@ mkChildInfo
241 (SearchResult { info: parentInfo, moduleName, name: resultName })
244 (SearchResult { info: parentInfo, moduleName, name: resultName })
242 (ChildDeclaration { info } )
245 (ChildDeclaration { info } )
243
246
244− | ChildDeclDataConstructor <- info.declType =
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
245− info.arguments <#> \arguments -> DataConstructorResult { arguments }
270+ info.arguments <#> \arguments ->
271+ DataConstructorResult { dataDeclType
272+ , "type": makeType arguments
273+ }
246
274
247 | ChildDeclTypeClassMember <- info.declType
275 | ChildDeclTypeClassMember <- info.declType
248 , TypeClassResult { arguments } <- parentInfo =
276 , TypeClassResult { arguments } <- parentInfo =
@@ -261,13 +289,14 @@ mkChildInfo
261
289
262 -- Then we construct a qualified name of the type class.
290 -- Then we construct a qualified name of the type class.
263 constraintClass =
291 constraintClass =
292+ QualifiedName { moduleNameParts:
264− QualifiedName { moduleName: String.split (wrap ".") moduleName
293+ String.split (wrap ".") $ unwrap moduleName
265 , name: resultName }
294 , name: resultName }
266
295
267 -- We concatenate two lists:
296 -- We concatenate two lists:
268 -- * a list of type parameters of the type class, and
297 -- * a list of type parameters of the type class, and
269 -- * a list of quantified variables of the unconstrained type
298 -- * 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 }
271 allArguments =
300 allArguments =
272 (arguments <#> unwrap) <> List.toUnfoldable binders
301 (arguments <#> unwrap) <> List.toUnfoldable binders
273
302
src/Docs/Search/DocsJson.purs+15−10
@@ -2,15 +2,16 @@
2module Docs.Search.DocsJson where
2module Docs.Search.DocsJson where
3
3
4import Prelude
4import Prelude
5−
5+import Prim hiding (Type, Constraint)
6−import Docs.Search.TypeDecoder (Constraint, FunDeps, Kind, Type, TypeArgument)
6+import Docs.Search.TypeDecoder (Constraint, FunDeps, Type, TypeArgument)
7
7
8import Data.Argonaut.Core (fromString, stringify, toString)
8import Data.Argonaut.Core (fromString, stringify, toString)
9import Data.Argonaut.Decode (class DecodeJson, decodeJson, (.:), (.:?))
9import Data.Argonaut.Decode (class DecodeJson, decodeJson, (.:), (.:?))
10+import Data.Argonaut.Decode.Error (JsonDecodeError(..))
10import Data.Argonaut.Encode (class EncodeJson, encodeJson)
11import Data.Argonaut.Encode (class EncodeJson, encodeJson)
11import Data.Either (Either(..))
12import Data.Either (Either(..))
12import Data.Generic.Rep (class Generic)
13import Data.Generic.Rep (class Generic)
13−import Data.Generic.Rep.Show (genericShow)
14+import Data.Show.Generic (genericShow)
14import Data.Maybe (Maybe(..))
15import Data.Maybe (Maybe(..))
15import Data.Newtype (class Newtype, unwrap)
16import Data.Newtype (class Newtype, unwrap)
16
17
@@ -43,7 +44,7 @@ newtype Declaration
43 , comments :: Maybe String
44 , comments :: Maybe String
44 , info :: { declType :: DeclType
45 , info :: { declType :: DeclType
45 , dataDeclType :: Maybe DataDeclType
46 , dataDeclType :: Maybe DataDeclType
46− , kind :: Maybe Kind
47+ , kind :: Maybe Type
47 , typeArguments :: Maybe (Array TypeArgument)
48 , typeArguments :: Maybe (Array TypeArgument)
48 , type :: Maybe Type
49 , type :: Maybe Type
49 , superclasses :: Maybe (Array Constraint)
50 , superclasses :: Maybe (Array Constraint)
@@ -151,7 +152,7 @@ instance encodeJsonDeclType :: EncodeJson DeclType where
151instance decodeJsonDeclType :: DecodeJson DeclType where
152instance decodeJsonDeclType :: DecodeJson DeclType where
152 decodeJson json =
153 decodeJson json =
153 case toString json of
154 case toString json of
154− Nothing -> Left $ "Couldn't decode DeclType: " <> stringify json
155+ Nothing -> errorWith $ "Couldn't decode DeclType: " <> stringify json
155 Just string ->
156 Just string ->
156 case string of
157 case string of
157 "value" -> Right DeclValue
158 "value" -> Right DeclValue
@@ -161,7 +162,7 @@ instance decodeJsonDeclType :: DecodeJson DeclType where
161 "typeClass" -> Right DeclTypeClass
162 "typeClass" -> Right DeclTypeClass
162 "alias" -> Right DeclAlias
163 "alias" -> Right DeclAlias
163 "kind" -> Right DeclExternKind
164 "kind" -> Right DeclExternKind
164− _ -> Left $ "Couldn't decode DeclType: " <> string
165+ _ -> errorWith $ "Couldn't decode DeclType: " <> string
165
166
166
167
167data ChildDeclType
168data ChildDeclType
@@ -184,13 +185,13 @@ instance encodeJsonChildDeclType :: EncodeJson ChildDeclType where
184instance decodeJsonChildDeclType :: DecodeJson ChildDeclType where
185instance decodeJsonChildDeclType :: DecodeJson ChildDeclType where
185 decodeJson json =
186 decodeJson json =
186 case toString json of
187 case toString json of
187− Nothing -> Left $ "Couldn't decode ChildDeclType: " <> stringify json
188+ Nothing -> errorWith $ "Couldn't decode ChildDeclType: " <> stringify json
188 Just tag ->
189 Just tag ->
189 case tag of
190 case tag of
190 "instance" -> Right ChildDeclInstance
191 "instance" -> Right ChildDeclInstance
191 "dataConstructor" -> Right ChildDeclDataConstructor
192 "dataConstructor" -> Right ChildDeclDataConstructor
192 "typeClassMember" -> Right ChildDeclTypeClassMember
193 "typeClassMember" -> Right ChildDeclTypeClassMember
193− _ -> Left $ "Couldn't decode ChildDeclType: " <> tag
194+ _ -> errorWith $ "Couldn't decode ChildDeclType: " <> tag
194
195
195
196
196data DataDeclType
197data DataDeclType
@@ -215,5 +216,9 @@ instance decodeJsonDataDeclType :: DecodeJson DataDeclType where
215 case tag of
216 case tag of
216 "newtype" -> Right NewtypeDataDecl
217 "newtype" -> Right NewtypeDataDecl
217 "data" -> Right DataDataDecl
218 "data" -> Right DataDataDecl
218− _ -> Left $ "Couldn't decode DataDeclType: " <> tag
219+ _ -> errorWith $ "Couldn't decode DataDeclType: " <> tag
219− Nothing -> Left $ "Couldn't decode DataDeclType: " <> stringify json
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)
5import Docs.Search.Score (Scores)
5import Docs.Search.Score (Scores)
6import Docs.Search.SearchResult (SearchResult, typeOfResult)
6import Docs.Search.SearchResult (SearchResult, typeOfResult)
7import Docs.Search.TypeQuery (TypeQuery(..), parseTypeQuery, penalty)
7import Docs.Search.TypeQuery (TypeQuery(..), parseTypeQuery, penalty)
8−import Docs.Search.Types (PackageName, ModuleName)
8+import Docs.Search.Types (PackageInfo(..), ModuleName(..), PackageName(..), PackageScore)
9
9
10import Prelude
10import Prelude
11
11
@@ -66,27 +66,34 @@ data Result
66 | MdlResult ModuleResult
66 | MdlResult ModuleResult
67
67
68
68
69−getResultScore :: Result -> Int
69+getResultScore :: Result -> PackageScore
70getResultScore (DeclResult r) = (unwrap r).score
70getResultScore (DeclResult r) = (unwrap r).score
71getResultScore (TypeResult r) = (unwrap r).score
71getResultScore (TypeResult r) = (unwrap r).score
72getResultScore (PackResult r) = r.score
72getResultScore (PackResult r) = r.score
73getResultScore (MdlResult r) = r.score
73getResultScore (MdlResult r) = r.score
74
74
75
75
76−getResultPackageName :: Result -> PackageName
76+getResultPackageInfo :: Result -> PackageInfo
77−getResultPackageName (DeclResult r) = (unwrap r).packageName
77+getResultPackageInfo (DeclResult r) = (unwrap r).packageInfo
78−getResultPackageName (TypeResult r) = (unwrap r).packageName
78+getResultPackageInfo (TypeResult r) = (unwrap r).packageInfo
79−getResultPackageName (PackResult r) = r.name
79+getResultPackageInfo (PackResult r) = Package r.name
80−getResultPackageName (MdlResult r) = r.package
80+getResultPackageInfo (MdlResult r) = r.package
81
81
82
82
83getResultModuleName :: Result -> ModuleName
83getResultModuleName :: Result -> ModuleName
84getResultModuleName (DeclResult r) = (unwrap r).moduleName
84getResultModuleName (DeclResult r) = (unwrap r).moduleName
85getResultModuleName (TypeResult r) = (unwrap r).moduleName
85getResultModuleName (TypeResult r) = (unwrap r).moduleName
86−getResultModuleName (PackResult r) = ""
86+getResultModuleName (PackResult r) = ModuleName ""
87getResultModuleName (MdlResult r) = r.name
87getResultModuleName (MdlResult r) = r.name
88
88
89
89
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+
90sortByPopularity
97sortByPopularity
91 :: forall index typeIndex
98 :: forall index typeIndex
92 . EngineState index typeIndex
99 . EngineState index typeIndex
@@ -95,8 +102,11 @@ sortByPopularity
95sortByPopularity { packageIndex } =
102sortByPopularity { packageIndex } =
96 Array.sortBy (
103 Array.sortBy (
97 compare `on` (getResultScore >>> negate) <>
104 compare `on` (getResultScore >>> negate) <>
98− compare `on` getResultPackageName <>
105+ compare `on` getResultPackageInfo <>
99− compare `on` getResultModuleName
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
100 )
110 )
101
111
102
112
@@ -148,3 +158,10 @@ sortByDistance
148 -> Array SearchResult
158 -> Array SearchResult
149sortByDistance typeQuery =
159sortByDistance typeQuery =
150 Array.sortWith (map (penalty typeQuery) <<< typeOfResult)
160 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 @@
1/* global __dirname require exports */
1/* global __dirname require exports */
2
2
3−var path = require('path');
3+import globMain from "glob";
4−var glob = require('glob');
5
4
6−exports.getDirname = function () {
5+export function getDirname () {
7 return __dirname;
6 return __dirname;
8};
7};
9
8
10−exports.glob = function (pattern) {
9+export function glob (pattern) {
11 return function () {
10 return function () {
12− return glob.sync(pattern);
11+ return globMain.sync(pattern);
13 };
12 };
14};
13};
src/Docs/Search/IndexBuilder.purs+70−25
@@ -1,21 +1,27 @@
1module Docs.Search.IndexBuilder where
1module Docs.Search.IndexBuilder where
2
2
3import Docs.Search.BrowserEngine (getPartId)
3import Docs.Search.BrowserEngine (getPartId)
4−import Docs.Search.Config (config)
4+import Docs.Search.Config as Config
5import Docs.Search.Declarations (Declarations(..), mkDeclarations)
5import Docs.Search.Declarations (Declarations(..), mkDeclarations)
6import Docs.Search.DocsJson (DocsJson)
6import Docs.Search.DocsJson (DocsJson)
7import Docs.Search.Extra ((>#>))
7import Docs.Search.Extra ((>#>))
8+import Docs.Search.Meta (Meta)
8import Docs.Search.ModuleIndex (PackedModuleIndex, mkPackedModuleIndex)
9import Docs.Search.ModuleIndex (PackedModuleIndex, mkPackedModuleIndex)
10+import Docs.Search.ModuleParser (parseModuleName)
9import Docs.Search.PackageIndex (PackageInfo, mkPackageInfo)
11import Docs.Search.PackageIndex (PackageInfo, mkPackageInfo)
10import Docs.Search.Score (mkScores)
12import Docs.Search.Score (mkScores)
11import Docs.Search.SearchResult (SearchResult)
13import Docs.Search.SearchResult (SearchResult)
12import Docs.Search.TypeIndex (TypeIndex, mkTypeIndex)
14import Docs.Search.TypeIndex (TypeIndex, mkTypeIndex)
15+import Docs.Search.Types (ModuleName, PackageName, PartId)
13
16
14import Prelude
17import Prelude
18+
15import Data.Argonaut.Core (stringify)
19import Data.Argonaut.Core (stringify)
16import Data.Argonaut.Decode (decodeJson)
20import Data.Argonaut.Decode (decodeJson)
21+import Data.Argonaut.Decode.Error (printJsonDecodeError)
17import Data.Argonaut.Encode (encodeJson)
22import Data.Argonaut.Encode (encodeJson)
18import Data.Argonaut.Parser (jsonParser)
23import Data.Argonaut.Parser (jsonParser)
24+import Data.Array (concat)
19import Data.Array as Array
25import Data.Array as Array
20import Data.Either (Either(..), either)
26import Data.Either (Either(..), either)
21import Data.Foldable (sum)
27import Data.Foldable (sum)
@@ -25,6 +31,7 @@ import Data.Map (Map)
25import Data.Map as Map
31import Data.Map as Map
26import Data.Maybe (Maybe(..), fromMaybe)
32import Data.Maybe (Maybe(..), fromMaybe)
27import Data.Newtype (unwrap)
33import Data.Newtype (unwrap)
34+import Data.Profunctor.Choice (left)
28import Data.Search.Trie as Trie
35import Data.Search.Trie as Trie
29import Data.Set as Set
36import Data.Set as Set
30import Data.String.CodePoints (contains) as String
37import Data.String.CodePoints (contains) as String
@@ -33,13 +40,15 @@ import Data.String.Common (replace) as String
33import Data.String.Pattern (Pattern(..), Replacement(..))
40import Data.String.Pattern (Pattern(..), Replacement(..))
34import Data.Traversable (for, for_)
41import Data.Traversable (for, for_)
35import Data.Tuple (Tuple(..), fst)
42import Data.Tuple (Tuple(..), fst)
43+import Data.Tuple.Nested ((/\))
36import Effect (Effect)
44import Effect (Effect)
37import Effect.Aff (Aff, launchAff_, parallel, sequential)
45import Effect.Aff (Aff, launchAff_, parallel, sequential)
38import Effect.Class (liftEffect)
46import Effect.Class (liftEffect)
39import Effect.Console (log)
47import Effect.Console (log)
40import Node.Encoding (Encoding(UTF8))
48import 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)
42import Node.FS.Stats (isDirectory, isFile)
50import Node.FS.Stats (isDirectory, isFile)
51+import Node.FS.Sync (exists)
43import Node.Process as Process
52import Node.Process as Process
44import Web.Bower.PackageMeta (PackageMeta(..))
53import Web.Bower.PackageMeta (PackageMeta(..))
45
54
@@ -49,6 +58,8 @@ type Config =
49 , bowerFiles :: Array String
58 , bowerFiles :: Array String
50 , generatedDocs :: String
59 , generatedDocs :: String
51 , noPatch :: Boolean
60 , noPatch :: Boolean
61+ , packageName :: PackageName
62+ , sourceFiles :: Array String
52 }
63 }
53
64
54
65
@@ -64,39 +75,44 @@ run' cfg = do
64 liftEffect do
75 liftEffect do
65 log "Building the search index..."
76 log "Building the search index..."
66
77
78+ docsJsons /\ moduleNames /\ packageMetas <- sequential $
79+ (\d h m -> d /\ h /\ m)
67− docsJsons <- decodeDocsJsons cfg
80+ <$> parallel (decodeDocsJsons cfg)
81+ <*> parallel (parseModuleHeaders cfg.sourceFiles)
68− packageMetas <- decodeBowerJsons cfg
82+ <*> parallel (decodeBowerJsons cfg)
83+
84+ let countOfPackages = Array.length packageMetas
85+ countOfModules = Array.length docsJsons
69
86
70 liftEffect do
87 liftEffect do
71 log $
88 log $
72 "Indexing " <>
89 "Indexing " <>
73− show (Array.length docsJsons) <>
90+ show countOfModules <>
74 " modules from " <>
91 " modules from " <>
75− show (Array.length packageMetas) <>
92+ show countOfPackages <>
76 " packages..."
93 " packages..."
77
94
78 let scores = mkScores packageMetas
95 let scores = mkScores packageMetas
79 index = mkDeclarations scores docsJsons
96 index = mkDeclarations scores docsJsons
80 typeIndex = mkTypeIndex scores docsJsons
97 typeIndex = mkTypeIndex scores docsJsons
81 packageInfo = mkPackageInfo scores packageMetas
98 packageInfo = mkPackageInfo scores packageMetas
82− moduleIndex = mkPackedModuleIndex index
99+ moduleIndex = mkPackedModuleIndex index moduleNames
100+ meta = { localPackageName: cfg.packageName }
83
101
84 createDirectories cfg
102 createDirectories cfg
85
103
86 void $ sequential do
104 void $ sequential do
87 ignore <$> parallel (writeIndex cfg index)
105 ignore <$> parallel (writeIndex cfg index)
88− <*> parallel (writeTypeIndex cfg typeIndex)
106+ <*> parallel (writeTypeIndex typeIndex)
89 <*> parallel (writePackageInfo packageInfo)
107 <*> parallel (writePackageInfo packageInfo)
90 <*> parallel (writeModuleIndex moduleIndex)
108 <*> parallel (writeModuleIndex moduleIndex)
91− <*> parallel (if cfg.noPatch
109+ <*> parallel (writeMeta meta)
92− then pure unit
93− else patchDocs cfg)
110+ <*> parallel (when (not cfg.noPatch) $ patchDocs cfg)
94 <*> parallel (copyAppFile cfg)
111 <*> parallel (copyAppFile cfg)
95
112
96 let countOfDefinitions = Trie.size $ unwrap index
113 let countOfDefinitions = Trie.size $ unwrap index
97 countOfTypeDefinitions =
114 countOfTypeDefinitions =
98 sum $ fromMaybe 0 <$> map Array.length <$> Map.values (unwrap typeIndex)
115 sum $ fromMaybe 0 <$> map Array.length <$> Map.values (unwrap typeIndex)
99− countOfPackages = Array.length packageMetas
100
116
101 liftEffect do
117 liftEffect do
102 log $
118 log $
@@ -146,7 +162,7 @@ decodeDocsJsons cfg@{ docsFiles } = do
146 if doesExist then do
162 if doesExist then do
147
163
148 contents <- readTextFile UTF8 jsonFile
164 contents <- readTextFile UTF8 jsonFile
149− let eiResult = jsonParser contents >>= decodeJson
165+ let eiResult = jsonParser contents >>= left printJsonDecodeError <<< decodeJson
150
166
151 case eiResult of
167 case eiResult of
152 Left error -> do
168 Left error -> do
@@ -167,6 +183,28 @@ decodeDocsJsons cfg@{ docsFiles } = do
167
183
168 pure docsJsons
184 pure docsJsons
169
185
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]
170
208
171decodeBowerJsons
209decodeBowerJsons
172 :: forall rest
210 :: forall rest
@@ -187,7 +225,7 @@ decodeBowerJsons { bowerFiles } = do
187 join <$> withExisting jsonFileName
225 join <$> withExisting jsonFileName
188 \contents ->
226 \contents ->
189 either (logError jsonFileName) pure
227 either (logError jsonFileName) pure
190− (jsonParser contents >>= decodeJson)
228+ (jsonParser contents >>= left printJsonDecodeError <<< decodeJson)
191
229
192 where
230 where
193 compareNames
231 compareNames
@@ -201,10 +239,10 @@ decodeBowerJsons { bowerFiles } = do
201
239
202
240
203-- | Write type index parts to files.
241-- | Write type index parts to files.
204−writeTypeIndex :: Config -> TypeIndex -> Aff Unit
242+writeTypeIndex :: TypeIndex -> Aff Unit
205−writeTypeIndex { generatedDocs } typeIndex =
243+writeTypeIndex typeIndex =
206 for_ entries \(Tuple typeShape results) -> do
244 for_ entries \(Tuple typeShape results) -> do
207− writeTextFile UTF8 (config.typeIndexDirectory <> "/" <> typeShape <> ".js")
245+ writeTextFile UTF8 (unwrap Config.typeIndexDirectory <> "/" <> typeShape <> ".js")
208 (mkHeader typeShape <> stringify (encodeJson results))
246 (mkHeader typeShape <> stringify (encodeJson results))
209 where
247 where
210 mkHeader typeShape =
248 mkHeader typeShape =
@@ -217,7 +255,7 @@ writeTypeIndex { generatedDocs } typeIndex =
217writePackageInfo :: PackageInfo -> Aff Unit
255writePackageInfo :: PackageInfo -> Aff Unit
218writePackageInfo packageInfo = do
256writePackageInfo packageInfo = do
219
257
220− writeTextFile UTF8 config.packageInfoPath $
258+ writeTextFile UTF8 (unwrap Config.packageInfoPath) $
221 header <> stringify (encodeJson packageInfo)
259 header <> stringify (encodeJson packageInfo)
222
260
223 where
261 where
@@ -226,15 +264,22 @@ writePackageInfo packageInfo = do
226
264
227writeModuleIndex :: PackedModuleIndex -> Aff Unit
265writeModuleIndex :: PackedModuleIndex -> Aff Unit
228writeModuleIndex moduleIndex = do
266writeModuleIndex moduleIndex = do
229− writeTextFile UTF8 config.moduleIndexPath $
267+ writeTextFile UTF8 (unwrap Config.moduleIndexPath) $
230 header <> stringify (encodeJson moduleIndex)
268 header <> stringify (encodeJson moduleIndex)
231 where
269 where
232 header = "window.DocsSearchModuleIndex = "
270 header = "window.DocsSearchModuleIndex = "
233
271
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+
234-- | Get a mapping from index parts to index contents.
279-- | 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)))
236getIndex (Declarations trie) =
281getIndex (Declarations trie) =
237− Array.foldr insert mempty parts
282+ Array.foldr insert Map.empty parts
238 where
283 where
239 insert part = Map.insertWith append (getPartId part.prefix) part.results
284 insert part = Map.insertWith append (getPartId part.prefix) part.results
240
285
@@ -249,7 +294,7 @@ getIndex (Declarations trie) =
249 Trie.query prefix trie
294 Trie.query prefix trie
250 else
295 else
251 -- Entries with path lengths > 1 have been added already.
296 -- 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) (
253 Trie.query prefix trie
298 Trie.query prefix trie
254 )
299 )
255 in
300 in
@@ -273,7 +318,7 @@ writeIndex { generatedDocs } = getIndex >>> \resultsMap -> do
273 "// This file was generated by purescript-docs-search.\n" <>
318 "// This file was generated by purescript-docs-search.\n" <>
274 "window.DocsSearchIndex[\"" <> show indexPartId <> "\"] = "
319 "window.DocsSearchIndex[\"" <> show indexPartId <> "\"] = "
275
320
276− writeTextFile UTF8 (generatedDocs <> config.mkIndexPartPath indexPartId) $
321+ writeTextFile UTF8 (generatedDocs <> Config.mkIndexPartPath indexPartId) $
277 header <> stringify (encodeJson results)
322 header <> stringify (encodeJson results)
278
323
279
324
@@ -354,7 +399,7 @@ copyAppFile { generatedDocs } = do
354
399
355directoryExists :: String -> Aff Boolean
400directoryExists :: String -> Aff Boolean
356directoryExists path = do
401directoryExists path = do
357− doesExist <- exists path
402+ doesExist <- liftEffect $ exists path
358 case doesExist of
403 case doesExist of
359 false -> pure false
404 false -> pure false
360 true -> isDirectory <$> stat path
405 true -> isDirectory <$> stat path
@@ -362,7 +407,7 @@ directoryExists path = do
362
407
363fileExists :: String -> Aff Boolean
408fileExists :: String -> Aff Boolean
364fileExists path = do
409fileExists path = do
365− doesExist <- exists path
410+ doesExist <- liftEffect $ exists path
366 case doesExist of
411 case doesExist of
367 false -> pure false
412 false -> pure false
368 true -> isFile <$> stat path
413 true -> isFile <$> stat path
src/Docs/Search/Interactive.purs+103−61
@@ -1,21 +1,12 @@
1-- | Definitions for the "search REPL".
1-- | Definitions for the "search REPL".
2module Docs.Search.Interactive where
2module Docs.Search.Interactive where
3
3
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)
14import Docs.Search.Declarations (Declarations, mkDeclarations)
4import Docs.Search.Declarations (Declarations, mkDeclarations)
15import Docs.Search.DocsJson (DataDeclType(..))
5import Docs.Search.DocsJson (DataDeclType(..))
16−import Docs.Search.Engine (mkEngineState, Result(..))
6+import Docs.Search.Engine (mkEngineState, packageInfoToString, Result(..))
17import Docs.Search.Engine as Engine
7import Docs.Search.Engine as Engine
18−import Docs.Search.Extra (listToString, stringToList, (>#>))
8+import Docs.Search.Extra (stringToList, (>#>))
9+import Docs.Search.IndexBuilder (parseModuleHeaders)
19import Docs.Search.IndexBuilder as IndexBuilder
10import Docs.Search.IndexBuilder as IndexBuilder
20import Docs.Search.ModuleIndex (ModuleResult, mkPackedModuleIndex, unpackModuleIndex)
11import Docs.Search.ModuleIndex (ModuleResult, mkPackedModuleIndex, unpackModuleIndex)
21import Docs.Search.NodeEngine (nodeEngine)
12import Docs.Search.NodeEngine (nodeEngine)
@@ -23,19 +14,36 @@ import Docs.Search.PackageIndex (PackageResult, mkPackageIndex, mkPackageInfo)
23import Docs.Search.Score (mkScores)
14import Docs.Search.Score (mkScores)
24import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
15import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
25import Docs.Search.Terminal (bold, cyan, green, yellow)
16import 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)
27import Docs.Search.TypeIndex (resultsWithTypes)
18import 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 ((/\))
29import Effect (Effect)
34import Effect (Effect)
30import Effect.Aff (launchAff_)
35import Effect.Aff (launchAff_)
31import Effect.Class (liftEffect)
36import Effect.Class (liftEffect)
32import Effect.Console (log, clear) as Console
37import Effect.Console (log, clear) as Console
33import Node.ReadLine (createConsoleInterface, question)
38import Node.ReadLine (createConsoleInterface, question)
39+import Prim hiding (Type, Constraint)
34
40
35
41
36type Config =
42type Config =
37 { docsFiles :: Array String
43 { docsFiles :: Array String
38 , bowerFiles :: Array String
44 , bowerFiles :: Array String
45+ , packageName :: PackageName
46+ , sourceFiles :: Array String
39 }
47 }
40
48
41
49
@@ -45,14 +53,17 @@ run cfg = launchAff_ $ do
45 liftEffect do
53 liftEffect do
46 Console.log "Loading search index..."
54 Console.log "Loading search index..."
47
55
56+ docsJsons /\ moduleNames /\ packageMetas <- sequential $
57+ (\d h m -> d /\ h /\ m)
48− docsJsons <- IndexBuilder.decodeDocsJsons cfg
58+ <$> parallel (IndexBuilder.decodeDocsJsons cfg)
59+ <*> parallel (parseModuleHeaders cfg.sourceFiles)
49− packageMetas <- IndexBuilder.decodeBowerJsons cfg
60+ <*> parallel (IndexBuilder.decodeBowerJsons cfg)
50
61
51 let scores = mkScores packageMetas
62 let scores = mkScores packageMetas
52 index = mkDeclarations scores docsJsons
63 index = mkDeclarations scores docsJsons
53 typeIndex = docsJsons >>= resultsWithTypes scores
64 typeIndex = docsJsons >>= resultsWithTypes scores
54 packageIndex = mkPackageIndex $ mkPackageInfo scores packageMetas
65 packageIndex = mkPackageIndex $ mkPackageInfo scores packageMetas
55− moduleIndex = unpackModuleIndex $ mkPackedModuleIndex index
66+ moduleIndex = unpackModuleIndex $ mkPackedModuleIndex index moduleNames
56 engineState = mkEngineState (unwrap index) typeIndex packageIndex moduleIndex scores
67 engineState = mkEngineState (unwrap index) typeIndex packageIndex moduleIndex scores
57
68
58 let countOfDefinitions = Trie.size $ unwrap index
69 let countOfDefinitions = Trie.size $ unwrap index
@@ -86,7 +97,7 @@ run cfg = launchAff_ $ do
86 Console.log $
97 Console.log $
87 if total > 0 then do
98 if total > 0 then do
88 Array.intercalate "\n\n\n" $
99 Array.intercalate "\n\n\n" $
89− showResult <$> Array.reverse results
100+ showResult cfg <$> Array.reverse results
90 else
101 else
91 "Your search for " <> bold input <> " did not yield any results."
102 "Your search for " <> bold input <> " did not yield any results."
92
103
@@ -103,60 +114,67 @@ mkCompleter
103 -> Effect { completions :: Array String
114 -> Effect { completions :: Array String
104 , matched :: String }
115 , matched :: String }
105mkCompleter index input = do
116mkCompleter index input = do
106− let path = stringToList input
117+ let path = stringToList $ String.toLower input
107− let paths =
118+ paths =
108 Array.fromFoldable $
119 Array.fromFoldable $
109− listToString <$>
120+ (\result -> unwrap (unwrap result).name) <$>
110− (fst <$> Trie.query path (unwrap index))
121+ List.concat (Trie.queryValues path (unwrap index))
111
122
112− pure { completions: paths
123+ pure { completions: paths, matched: input }
113− , matched: input }
114
124
115
125
116−showResult :: Result -> String
126+showResult :: Config -> Result -> String
117−showResult = case _ of
127+showResult cfg = case _ of
118− DeclResult r -> showSearchResult r
128+ DeclResult r -> showSearchResult cfg r
119− TypeResult r -> showSearchResult r
129+ TypeResult r -> showSearchResult cfg r
120 PackResult r -> showPackageResult r
130 PackResult r -> showPackageResult r
121 MdlResult r -> showModuleResult r
131 MdlResult r -> showModuleResult r
122
132
123
133
124−showSearchResult :: SearchResult -> String
134+showSearchResult :: Config -> SearchResult -> String
125−showSearchResult (SearchResult result@{ name, comments, moduleName, packageName }) =
135+showSearchResult cfg (SearchResult result@{ name, comments, moduleName, packageInfo }) =
126 showSignature result <> "\n" <>
136 showSignature result <> "\n" <>
127
137
128 (fromMaybe "\n" $
138 (fromMaybe "\n" $
129 comments <#> \comment ->
139 comments <#> \comment ->
130 "\n" <> leftShift 3 (String.trim comment) <> "\n\n") <>
140 "\n" <> leftShift 3 (String.trim comment) <> "\n\n") <>
131
141
142+ bold (
132− bold (cyan (rightPad 40 packageName)) <> space <> bold (green moduleName)
143+ cyan (rightPad 40 $ packageInfoToString cfg.packageName packageInfo)
144+ ) <>
145+ space <>
146+ showModuleName moduleName
133
147
134
148
135showPackageResult :: PackageResult -> String
149showPackageResult :: PackageResult -> String
136showPackageResult { name, description } =
150showPackageResult { name, description } =
137− bold (cyan "package") <> " " <> bold (yellow name) <>
151+ bold (cyan "package") <> " " <> bold (yellow $ unwrap name) <>
138
152
139 (description >#> \text -> "\n\n" <> leftShift 3 text <> "\n")
153 (description >#> \text -> "\n\n" <> leftShift 3 text <> "\n")
140
154
141
155
142showModuleResult :: ModuleResult -> String
156showModuleResult :: ModuleResult -> String
143showModuleResult { name, package } =
157showModuleResult { name, package } =
144− bold (cyan "module") <> " " <> bold (green name)
158+ bold (cyan "module") <> " " <> showModuleName name
145
159
146
160
161+showModuleName :: ModuleName -> String
162+showModuleName = bold <<< green <<< unwrap
163+
164+
147−showSignature ::
165+showSignature
148− forall rest.
166+ :: forall rest
149− { name :: String
167+ . { name :: Identifier
150− , moduleName :: String
168+ , moduleName :: ModuleName
151− , packageName :: String
169+ , packageInfo :: PackageInfo
152− , info :: ResultInfo
170+ , info :: ResultInfo
153− | rest
171+ | rest
154− }
172+ }
155 -> String
173 -> String
156showSignature result@{ name, info } =
174showSignature result@{ name, info } =
157 case info of
175 case info of
158 ValueResult { type: ty } ->
176 ValueResult { type: ty } ->
159− yellow name <> syntax " :: " <> showType ty
177+ yellow (unwrap name) <> syntax " :: " <> showType ty
160
178
161 TypeClassResult info' ->
179 TypeClassResult info' ->
162 showTypeClassSignature info' result
180 showTypeClassSignature info' result
@@ -174,9 +192,12 @@ showSignature result@{ name, info } =
174 showExternDataSignature info' result
192 showExternDataSignature info' result
175
193
176 ValueAliasResult ->
194 ValueAliasResult ->
177− yellow ("(" <> name <> ")")
195+ yellow ("(" <> unwrap name <> ")")
196+
197+ DataConstructorResult info' ->
198+ showDataConstructorSignature info' result
178
199
179− _ -> yellow name
200+ _ -> yellow $ unwrap name
180
201
181
202
182showTypeClassSignature
203showTypeClassSignature
@@ -185,7 +206,7 @@ showTypeClassSignature
185 , arguments :: Array TypeArgument
206 , arguments :: Array TypeArgument
186 , superclasses :: Array Constraint
207 , superclasses :: Array Constraint
187 }
208 }
188− -> { name :: String, moduleName :: String | rest }
209+ -> { name :: Identifier, moduleName :: ModuleName | rest }
189 -> String
210 -> String
190showTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName } =
211showTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName } =
191
212
@@ -199,12 +220,11 @@ showTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName }
199 superclasses <#> showConstraint
220 superclasses <#> showConstraint
200 )
221 )
201 ) <>
222 ) <>
202− syntax ")" <>
223+ syntax ") " <>
203− space <>
204 syntax "<="
224 syntax "<="
205 ) <>
225 ) <>
206 space <>
226 space <>
207− yellow name <>
227+ yellow (unwrap name) <>
208 space <> (
228 space <> (
209 Array.intercalate space $
229 Array.intercalate space $
210 arguments <#> showTypeArgument
230 arguments <#> showTypeArgument
@@ -215,14 +235,14 @@ showTypeClassSignature { fundeps, arguments, superclasses } { name, moduleName }
215
235
216showTypeClassMemberSignature
236showTypeClassMemberSignature
217 :: forall rest
237 :: forall rest
218− . { type :: Type
238+ . { "type" :: Type
219 , typeClass :: QualifiedName
239 , typeClass :: QualifiedName
220 , typeClassArguments :: Array TypeArgument
240 , typeClassArguments :: Array TypeArgument
221 }
241 }
222− -> { name :: String | rest }
242+ -> { name :: Identifier | rest }
223 -> String
243 -> String
224−showTypeClassMemberSignature { type: ty, typeClass, typeClassArguments } result =
244+showTypeClassMemberSignature { "type": ty, typeClass, typeClassArguments } result =
225− yellow result.name <>
245+ yellow (unwrap result.name) <>
226 syntax " :: " <>
246 syntax " :: " <>
227 showType ty
247 showType ty
228
248
@@ -231,7 +251,7 @@ showDataSignature
231 :: forall rest
251 :: forall rest
232 . { typeArguments :: Array TypeArgument
252 . { typeArguments :: Array TypeArgument
233 , dataDeclType :: DataDeclType }
253 , dataDeclType :: DataDeclType }
234− -> { name :: String | rest }
254+ -> { name :: Identifier | rest }
235 -> String
255 -> String
236showDataSignature { typeArguments, dataDeclType } { name } =
256showDataSignature { typeArguments, dataDeclType } { name } =
237 ( keyword
257 ( keyword
@@ -240,7 +260,7 @@ showDataSignature { typeArguments, dataDeclType } { name } =
240 DataDataDecl -> "data"
260 DataDataDecl -> "data"
241 ) <>
261 ) <>
242 space <>
262 space <>
243− yellow name <>
263+ yellow (unwrap name) <>
244 space <> (
264 space <> (
245 Array.intercalate space $
265 Array.intercalate space $
246 typeArguments <#> showTypeArgument
266 typeArguments <#> showTypeArgument
@@ -252,12 +272,12 @@ showTypeSynonymSignature
252 . { type :: Type
272 . { type :: Type
253 , arguments :: Array TypeArgument
273 , arguments :: Array TypeArgument
254 }
274 }
255− -> { name :: String | rest }
275+ -> { name :: Identifier | rest }
256 -> String
276 -> String
257showTypeSynonymSignature { type: ty, arguments } { name } =
277showTypeSynonymSignature { type: ty, arguments } { name } =
258 keyword "type" <>
278 keyword "type" <>
259 space <>
279 space <>
260− yellow name <>
280+ yellow (unwrap name) <>
261 space <> (
281 space <> (
262 Array.intercalate space $
282 Array.intercalate space $
263 arguments <#> showTypeArgument
283 arguments <#> showTypeArgument
@@ -270,16 +290,38 @@ showTypeSynonymSignature { type: ty, arguments } { name } =
270
290
271showExternDataSignature
291showExternDataSignature
272 :: forall rest
292 :: forall rest
273− . { kind :: Kind }
293+ . { kind :: Type }
274− -> { name :: String | rest }
294+ -> { name :: Identifier | rest }
275 -> String
295 -> String
276showExternDataSignature { kind } { name } =
296showExternDataSignature { kind } { name } =
277 keyword "foreign data" <>
297 keyword "foreign data" <>
278 space <>
298 space <>
279− yellow name <>
299+ yellow (unwrap name) <>
280− space <>
281 syntax " :: " <>
300 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
283
325
284
326
285leftShift :: Int -> String -> String
327leftShift :: 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 @@
1-- | The main module of the CLI interface app.
1-- | The main module of the CLI interface app.
2module Docs.Search.Main where
2module Docs.Search.Main where
3
3
4−import Prelude
4+import Docs.Search.Config as Config
5−
6import Docs.Search.IndexBuilder as IndexBuilder
5import Docs.Search.IndexBuilder as IndexBuilder
7import Docs.Search.Interactive as Interactive
6import Docs.Search.Interactive as Interactive
8−import Docs.Search.Config (config)
7+import Docs.Search.Types (PackageName(..))
8+
9+import Prelude
9
10
10import Data.Generic.Rep (class Generic)
11import Data.Generic.Rep (class Generic)
11−import Data.Generic.Rep.Show (genericShow)
12import Data.List as List
12import Data.List as List
13import Data.List.NonEmpty as NonEmpty
13import Data.List.NonEmpty as NonEmpty
14import Data.Maybe (Maybe, fromMaybe, optional)
14import Data.Maybe (Maybe, fromMaybe, optional)
15+import Data.Newtype (unwrap)
16+import Data.Show.Generic (genericShow)
15import Data.Unfoldable (class Unfoldable)
17import Data.Unfoldable (class Unfoldable)
16import Effect (Effect)
18import Effect (Effect)
17import Effect.Console (log)
19import Effect.Console (log)
@@ -23,13 +25,16 @@ main :: Effect Unit
23main = do
25main = do
24
26
25 args <- getArgs
27 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+ }
27
33
28 case fromMaybe defaultCommands args of
34 case fromMaybe defaultCommands args of
29 BuildIndex cfg -> IndexBuilder.run cfg
35 BuildIndex cfg -> IndexBuilder.run cfg
30 Search cfg -> Interactive.run cfg
36 Search cfg -> Interactive.run cfg
31− Version -> log config.version
37+ Version -> log Config.version
32−
33
38
34getArgs :: Effect (Maybe Commands)
39getArgs :: Effect (Maybe Commands)
35getArgs = execParser opts
40getArgs = execParser opts
@@ -40,27 +45,16 @@ getArgs = execParser opts
40 <> progDesc "Search frontend for the documentation generated by the PureScript compiler."
45 <> progDesc "Search frontend for the documentation generated by the PureScript compiler."
41 )
46 )
42
47
43−
44data Commands
48data Commands
45− = BuildIndex
49+ = BuildIndex IndexBuilder.Config
46− { docsFiles :: Array String
47− , bowerFiles :: Array String
48− , generatedDocs :: String
49− , noPatch :: Boolean
50− }
51− | Search
50+ | Search Interactive.Config
52− { docsFiles :: Array String
53− , bowerFiles :: Array String
54− }
55 | Version
51 | Version
56
52
57−
58derive instance genericCommands :: Generic Commands _
53derive instance genericCommands :: Generic Commands _
59
54
60instance showCommands :: Show Commands where
55instance showCommands :: Show Commands where
61 show = genericShow
56 show = genericShow
62
57
63−
64commands :: Parser (Maybe Commands)
58commands :: Parser (Maybe Commands)
65commands = optional $ subparser
59commands = optional $ subparser
66 ( command "build-index"
60 ( command "build-index"
@@ -83,34 +77,30 @@ commands = optional $ subparser
83
77
84buildIndex :: Parser Commands
78buildIndex :: Parser Commands
85buildIndex = ado
79buildIndex = ado
86−
87 docsFiles <- docsFilesOption
80 docsFiles <- docsFilesOption
88−
89 bowerFiles <- bowerFilesOption
81 bowerFiles <- bowerFilesOption
90−
82+ packageName <- packageNameOption
83+ sourceFiles <- sourceFilesOption
91 generatedDocs <- strOption
84 generatedDocs <- strOption
92 ( long "generated-docs"
85 ( long "generated-docs"
93 <> metavar "DIR"
86 <> metavar "DIR"
94 <> value "./generated-docs/"
87 <> value "./generated-docs/"
88+ <> help "Path to the generated documentation HTML that will be patched. Search app will be injected into each HTML document."
95 )
89 )
96−
97 noPatch <- flag false true
90 noPatch <- flag false true
98 ( long "no-patch"
91 ( long "no-patch"
99 <> help "Do not patch the HTML docs, only build indices"
92 <> help "Do not patch the HTML docs, only build indices"
100 )
93 )
101−
102− in BuildIndex { docsFiles, bowerFiles, generatedDocs, noPatch }
94+ in BuildIndex { docsFiles, bowerFiles, generatedDocs, noPatch, packageName, sourceFiles }
103
95
104
96
105startInteractive :: Parser Commands
97startInteractive :: Parser Commands
106startInteractive = ado
98startInteractive = ado
107−
108 docsFiles <- docsFilesOption
99 docsFiles <- docsFilesOption
109−
110 bowerFiles <- bowerFilesOption
100 bowerFiles <- bowerFilesOption
111−
101+ packageName <- packageNameOption
102+ sourceFiles <- sourceFilesOption
112− in Search { docsFiles, bowerFiles }
103+ in Search { docsFiles, bowerFiles, packageName, sourceFiles }
113−
114
104
115docsFilesOption :: Parser (Array String)
105docsFilesOption :: Parser (Array String)
116docsFilesOption = fromMaybe defaultDocsFiles <$>
106docsFilesOption = fromMaybe defaultDocsFiles <$>
@@ -119,11 +109,11 @@ docsFilesOption = fromMaybe defaultDocsFiles <$>
119 ( strOption
109 ( strOption
120 ( long "docs-files"
110 ( long "docs-files"
121 <> metavar "GLOB"
111 <> metavar "GLOB"
112+ <> help "Glob that captures `docs.json` files that should be used to build the index"
122 )
113 )
123 )
114 )
124 )
115 )
125
116
126−
127bowerFilesOption :: Parser (Array String)
117bowerFilesOption :: Parser (Array String)
128bowerFilesOption = fromMaybe defaultBowerFiles <$>
118bowerFilesOption = fromMaybe defaultBowerFiles <$>
129 optional
119 optional
@@ -131,22 +121,43 @@ bowerFilesOption = fromMaybe defaultBowerFiles <$>
131 ( strOption
121 ( strOption
132 ( long "bower-jsons"
122 ( long "bower-jsons"
133 <> metavar "GLOB"
123 <> 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."
134 )
125 )
135 )
126 )
136 )
127 )
137
128
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+ )
138
149
139defaultDocsFiles :: Array String
150defaultDocsFiles :: Array String
140defaultDocsFiles = [ "output/**/docs.json" ]
151defaultDocsFiles = [ "output/**/docs.json" ]
141
152
142−
143defaultBowerFiles :: Array String
153defaultBowerFiles :: Array String
144defaultBowerFiles = [ ".spago/*/*/bower.json", "bower_components/purescript-*/bower.json" ]
154defaultBowerFiles = [ ".spago/*/*/bower.json", "bower_components/purescript-*/bower.json" ]
145
155
156+defaultSourceFiles :: Array String
157+defaultSourceFiles = [ "src/**/*.purs" ]
146
158
147many :: forall a f. Unfoldable f => Parser a -> Parser (f a)
159many :: forall a f. Unfoldable f => Parser a -> Parser (f a)
148many x = CA.many x <#> List.toUnfoldable
160many x = CA.many x <#> List.toUnfoldable
149
161
150−
151some :: forall a f. Unfoldable f => Parser a -> Parser (f a)
162some :: forall a f. Unfoldable f => Parser a -> Parser (f a)
152some x = CA.some x <#> NonEmpty.toUnfoldable
163some 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 @@
1/* global exports */
1/* global exports */
2
2
3−exports.load = function (url) {
3+export function load (url) {
4 return function () {
4 return function () {
5 return new Promise(function (resolve, reject) {
5 return new Promise(function (resolve, reject) {
6 if (typeof window.DocsSearchModuleIndex === 'undefined') {
6 if (typeof window.DocsSearchModuleIndex === 'undefined') {
src/Docs/Search/ModuleIndex.purs+36−29
@@ -1,11 +1,11 @@
1module Docs.Search.ModuleIndex where
1module Docs.Search.ModuleIndex where
2
2
3−import Docs.Search.Config (config)
3+import Docs.Search.Config as Config
4import Docs.Search.Declarations (Declarations(..))
4import Docs.Search.Declarations (Declarations(..))
5−import Docs.Search.SearchResult (SearchResult(..))
6−import Docs.Search.Types (ModuleName, PackageName)
7import Docs.Search.Extra (stringToList)
5import 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)
9
9
10import Prelude
10import Prelude
11
11
@@ -21,7 +21,8 @@ import Data.Lens.Record (prop)
21import Data.List (List, (:))
21import Data.List (List, (:))
22import Data.Map (Map)
22import Data.Map (Map)
23import Data.Map as Map
23import Data.Map as Map
24−import Data.Maybe (fromMaybe)
24+import Data.Maybe (Maybe(..), fromMaybe)
25+import Data.Newtype (unwrap)
25import Data.Search.Trie (Trie)
26import Data.Search.Trie (Trie)
26import Data.Search.Trie as Trie
27import Data.Search.Trie as Trie
27import Data.Set (Set)
28import Data.Set (Set)
@@ -29,37 +30,36 @@ import Data.Set as Set
29import Data.String.CodeUnits (toCharArray) as String
30import Data.String.CodeUnits (toCharArray) as String
30import Data.String.Common (split, toLower) as String
31import Data.String.Common (split, toLower) as String
31import Data.String.Pattern (Pattern(..))
32import Data.String.Pattern (Pattern(..))
32−import Data.Symbol (SProxy(..))
33import Data.Traversable (foldr, for_)
33import Data.Traversable (foldr, for_)
34import Data.Tuple.Nested ((/\))
34import Data.Tuple.Nested ((/\))
35import Effect (Effect)
35import Effect (Effect)
36import Effect.Aff (Aff)
36import Effect.Aff (Aff)
37−
37+import Type.Proxy (Proxy(..))
38
38
39-- | Module index that is actually stored in a JS file.
39-- | Module index that is actually stored in a JS file.
40−type PackedModuleIndex = Map PackageName (Set ModuleName)
40+type PackedModuleIndex = Map PackageInfo (Set ModuleName)
41
41
42-- | "Expanded" module index that can be queried quickly.
42-- | "Expanded" module index that can be queried quickly.
43−type ModuleIndex = { packageModules :: Map PackageName (Set ModuleName)
43+type ModuleIndex = { packageModules :: Map PackageInfo (Set ModuleName)
44− , modulePackages :: Map ModuleName PackageName
44+ , modulePackages :: Map ModuleName PackageInfo
45 , index :: Trie Char ModuleName
45 , index :: Trie Char ModuleName
46 }
46 }
47
47
48
48
49type ModuleResult
49type ModuleResult
50 = { name :: ModuleName
50 = { name :: ModuleName
51− , package :: PackageName
51+ , package :: PackageInfo
52− , score :: Int
52+ , score :: PackageScore
53 }
53 }
54
54
55
55
56unpackModuleIndex :: PackedModuleIndex -> ModuleIndex
56unpackModuleIndex :: PackedModuleIndex -> ModuleIndex
57unpackModuleIndex packageModules =
57unpackModuleIndex packageModules =
58− flip execState { packageModules, modulePackages: mempty, index: mempty } do
58+ flip execState { packageModules, modulePackages: Map.empty, index: mempty } do
59 for_ (Map.toUnfoldableUnordered packageModules :: Array _)
59 for_ (Map.toUnfoldableUnordered packageModules :: Array _)
60− \(packageName /\ moduleNames) -> do
60+ \(package /\ moduleNames) -> do
61 for_ moduleNames \moduleName -> do
61 for_ moduleNames \moduleName -> do
62− modify_ $ _modulePackages %~ Map.insert moduleName packageName
62+ modify_ $ _modulePackages %~ Map.insert moduleName package
63 for_ (extractModuleNameParts moduleName) \part -> do
63 for_ (extractModuleNameParts moduleName) \part -> do
64 let partPath = Array.toUnfoldable $ String.toCharArray part
64 let partPath = Array.toUnfoldable $ String.toCharArray part
65 modify_ $ _index %~ Trie.insert partPath moduleName
65 modify_ $ _index %~ Trie.insert partPath moduleName
@@ -68,7 +68,9 @@ unpackModuleIndex packageModules =
68-- | E.g. `"Data.Array.ST" -> ["data.array.st", "array.st", "st"]`.
68-- | E.g. `"Data.Array.ST" -> ["data.array.st", "array.st", "st"]`.
69extractModuleNameParts :: ModuleName -> List String
69extractModuleNameParts :: ModuleName -> List String
70extractModuleNameParts =
70extractModuleNameParts =
71+ unwrap >>> String.toLower >>>
72+ String.split (Pattern ".") >>>
71− foldl (\acc el -> el : map (_ <> "." <> el) acc) mempty <<< String.split (Pattern ".") <<< String.toLower
73+ foldl (\acc el -> el : map (_ <> "." <> el) acc) mempty
72
74
73
75
74queryModuleIndex
76queryModuleIndex
@@ -83,28 +85,33 @@ queryModuleIndex scores { index, modulePackages } query =
83 Array.nub <#>
85 Array.nub <#>
84 (\name -> do
86 (\name -> do
85 package <- Map.lookup name modulePackages
87 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 }) #
87 Array.catMaybes
90 Array.catMaybes
88
91
89
92
90-- | Constructs a mapping from packages to modules
93-- | Constructs a mapping from packages to modules
91−mkPackedModuleIndex :: Declarations -> PackedModuleIndex
94+mkPackedModuleIndex :: Declarations -> Array ModuleName -> PackedModuleIndex
92−mkPackedModuleIndex (Declarations trie) =
95+mkPackedModuleIndex (Declarations trie) moduleNames =
96+ addLocalPackageModuleNames $
93− foldr (Map.unionWith Set.union) mempty $ extract <$> Trie.values trie
97+ foldr (Map.unionWith Set.union) Map.empty $ extract <$> Trie.values trie
94 where
98 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
95 extract
103 extract
96 :: List SearchResult
104 :: List SearchResult
97− -> Map PackageName (Set ModuleName)
105+ -> Map PackageInfo (Set ModuleName)
98− extract = foldr (Map.unionWith Set.union) mempty <<< map mkEntry
106+ extract = foldr (Map.unionWith Set.union) Map.empty <<< map mkEntry
99 where
107 where
100− mkEntry (SearchResult { packageName, moduleName }) =
108+ mkEntry (SearchResult { packageInfo, moduleName }) =
101− Map.singleton packageName (Set.singleton moduleName)
109+ Map.singleton packageInfo (Set.singleton moduleName)
102−
103
110
104loadModuleIndex :: Aff PackedModuleIndex
111loadModuleIndex :: Aff PackedModuleIndex
105loadModuleIndex = do
112loadModuleIndex = do
106− json <- toAffE $ load config.moduleIndexLoadPath
113+ json <- toAffE $ load Config.moduleIndexLoadPath
107− pure $ fromMaybe mempty $ hush $ decodeJson json
114+ pure $ fromMaybe Map.empty $ hush $ decodeJson json
108
115
109
116
110foreign import load
117foreign import load
@@ -113,7 +120,7 @@ foreign import load
113
120
114
121
115_modulePackages :: forall a b rest. (a -> b) -> { modulePackages :: a | rest } -> { modulePackages :: b | rest }
122_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")
117
124
118_index :: forall a b rest. (a -> b) -> { index :: a | rest } -> { index :: b | rest }
125_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 @@
1module Docs.Search.PackageIndex where
1module Docs.Search.PackageIndex where
2
2
3−import Docs.Search.Config (config)
3+import Docs.Search.Config as Config
4import Docs.Search.Extra (stringToList)
4import 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
6
8
7import Prelude
9import Prelude
8
10
9−import Control.Promise (Promise, toAffE)
10−import Data.Argonaut.Core (Json)
11−import Data.Argonaut.Decode (decodeJson)
12import Data.Array as Array
11import Data.Array as Array
13−import Data.Either (hush)
14import Data.Map (Map)
12import Data.Map (Map)
15import Data.Map as Map
13import Data.Map as Map
16−import Data.Maybe (Maybe, fromMaybe)
14+import Data.Maybe (Maybe)
17import Data.Newtype (unwrap)
15import Data.Newtype (unwrap)
18import Data.Search.Trie (Trie)
16import Data.Search.Trie (Trie)
19import Data.Search.Trie as Trie
17import Data.Search.Trie as Trie
20−import Effect (Effect)
21import Effect.Aff (Aff)
18import Effect.Aff (Aff)
22import Web.Bower.PackageMeta (PackageMeta(..))
19import Web.Bower.PackageMeta (PackageMeta(..))
23
20
24
21
25type PackageResult
22type PackageResult
26− = { name :: String
23+ = { name :: PackageName
27 , description :: Maybe String
24 , description :: Maybe String
28− , score :: Int
25+ , score :: PackageScore
29− , dependencies :: Array String
26+ , dependencies :: Array PackageName
30 , repository :: Maybe String
27 , repository :: Maybe String
31 }
28 }
32
29
@@ -39,46 +36,47 @@ mkPackageInfo :: Scores -> Array PackageMeta -> PackageInfo
39mkPackageInfo packageScores pms =
36mkPackageInfo packageScores pms =
40 Array.fromFoldable $
37 Array.fromFoldable $
41 Map.values $
38 Map.values $
42− Array.foldr insert mempty pms
39+ Array.foldr insert Map.empty pms
43
40
44 where
41 where
45 insert
42 insert
46 :: PackageMeta
43 :: PackageMeta
47− -> Map String PackageResult
44+ -> Map PackageName PackageResult
48− -> Map String PackageResult
45+ -> Map PackageName PackageResult
49 insert
46 insert
50 (PackageMeta { name
47 (PackageMeta { name
51 , description
48 , description
52 , dependencies
49 , dependencies
53 , devDependencies
50 , devDependencies
54 , repository }) =
51 , repository }) =
55−
56− Map.insert
52+ Map.insert
57− name
53+ packageName
58− { name
54+ { name: packageName
59 , description: description
55 , description: description
60− , score: getPackageScore packageScores $ normalizePackageName name
56+ , score: getPackageScoreForPackageName packageScores packageName
57+ , dependencies:
61− , dependencies: unwrap dependencies <#> (_.packageName)
58+ unwrap dependencies <#>
59+ _.packageName >>> RawPackageName >>> normalizePackageName
62 , repository: repository <#> (_.url)
60 , repository: repository <#> (_.url)
63 }
61 }
64
62
63+ where packageName = normalizePackageName $ RawPackageName name
65
64
66mkScoresFromPackageIndex :: PackageIndex -> Scores
65mkScoresFromPackageIndex :: PackageIndex -> Scores
67mkScoresFromPackageIndex =
66mkScoresFromPackageIndex =
67+ Trie.values >>> Array.fromFoldable >>>
68− Trie.values >>> Array.foldr (\ { name, score } -> Map.insert name score) mempty
68+ Array.foldr (\ { name, score } -> Map.insert name score) Map.empty
69
69
70
70
71loadPackageIndex :: Aff PackageIndex
71loadPackageIndex :: Aff PackageIndex
72−loadPackageIndex = do
72+loadPackageIndex =
73− json <- toAffE (load config.packageInfoLoadPath)
73+ mkPackageIndex <$> Loader.load Config.packageInfoItem Config.packageInfoLoadPath
74− let packageInfo = fromMaybe mempty $ hush $ decodeJson json
75− pure $ mkPackageIndex packageInfo
76
74
77
75
78mkPackageIndex :: PackageInfo -> PackageIndex
76mkPackageIndex :: PackageInfo -> PackageIndex
79mkPackageIndex =
77mkPackageIndex =
80 Array.foldr
78 Array.foldr
81− (\package -> Trie.insert (stringToList $ normalizePackageName package.name) package)
79+ (\package -> Trie.insert (stringToList $ unwrap package.name) package)
82 mempty
80 mempty
83
81
84
82
@@ -94,8 +92,3 @@ queryPackageIndex index query =
94 pure { index
92 pure { index
95 , results: Array.fromFoldable $ Trie.queryValues (stringToList query) index
93 , results: Array.fromFoldable $ Trie.queryValues (stringToList query) index
96 }
94 }
97−
98−
99−foreign import load
100− :: String
101− -> Effect (Promise Json)
src/Docs/Search/Score.purs+20−15
@@ -1,6 +1,6 @@
1module Docs.Search.Score where
1module Docs.Search.Score where
2
2
3−import Docs.Search.Types (PackageName)
3+import Docs.Search.Types (RawPackageName(..), PackageName(..), PackageInfo(..), PackageScore(..))
4
4
5import Prelude
5import Prelude
6
6
@@ -13,18 +13,11 @@ import Data.String.CodeUnits as String
13import Web.Bower.PackageMeta (Dependencies, PackageMeta)
13import Web.Bower.PackageMeta (Dependencies, PackageMeta)
14
14
15
15
16−type Scores = Map PackageName Int
16+type Scores = Map PackageName PackageScore
17
17
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
18+normalizePackageName :: RawPackageName -> PackageName
26−normalizePackageName packageName =
19+normalizePackageName (RawPackageName p) =
27− fromMaybe packageName $ String.stripPrefix (wrap "purescript-") packageName
20+ fromMaybe (PackageName p) $ map wrap $ String.stripPrefix (wrap "purescript-") p
28
21
29
22
30-- | Construct a mapping from package names to their scores, based on number
23-- | Construct a mapping from package names to their scores, based on number
@@ -36,12 +29,24 @@ mkScores =
36 updateScoresFor (unwrap pm).dependencies >>>
29 updateScoresFor (unwrap pm).dependencies >>>
37 updateScoresFor (unwrap pm).devDependencies
30 updateScoresFor (unwrap pm).devDependencies
38 )
31 )
39− mempty
32+ Map.empty
40
33
41 where
34 where
42 updateScoresFor :: Dependencies -> Scores -> Scores
35 updateScoresFor :: Dependencies -> Scores -> Scores
43 updateScoresFor deps scores =
36 updateScoresFor deps scores =
44 Array.foldr
37 Array.foldr
45− (\dep -> Map.insertWith add dep 1)
38+ (\dep -> Map.insertWith add dep one)
46 scores
39 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 @@
1module Docs.Search.SearchResult where
1module Docs.Search.SearchResult where
2
2
3import Docs.Search.DocsJson (DataDeclType)
3import 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)
5
6
6import Prelude
7import Prelude
7−
8+import Prim hiding (Type, Constraint)
8import Data.Argonaut.Decode (class DecodeJson)
9import Data.Argonaut.Decode (class DecodeJson)
9−import Data.Argonaut.Decode.Generic.Rep (genericDecodeJson)
10+import Data.Argonaut.Decode.Generic (genericDecodeJson)
10import Data.Argonaut.Encode (class EncodeJson)
11import Data.Argonaut.Encode (class EncodeJson)
11−import Data.Argonaut.Encode.Generic.Rep (genericEncodeJson)
12+import Data.Argonaut.Encode.Generic (genericEncodeJson)
12import Data.Generic.Rep (class Generic)
13import Data.Generic.Rep (class Generic)
13import Data.Maybe (Maybe(..))
14import Data.Maybe (Maybe(..))
14import Data.Newtype (class Newtype, un)
15import Data.Newtype (class Newtype, un)
@@ -18,10 +19,11 @@ import Data.Newtype (class Newtype, un)
18data ResultInfo
19data ResultInfo
19 = DataResult { typeArguments :: Array TypeArgument
20 = DataResult { typeArguments :: Array TypeArgument
20 , dataDeclType :: DataDeclType }
21 , dataDeclType :: DataDeclType }
21− | ExternDataResult { kind :: Kind }
22+ | ExternDataResult { kind :: Type }
22 | TypeSynonymResult { arguments :: Array TypeArgument
23 | TypeSynonymResult { arguments :: Array TypeArgument
23 , type :: Type }
24 , type :: Type }
24− | DataConstructorResult { arguments :: Array Type }
25+ | DataConstructorResult { dataDeclType :: DataDeclType
26+ , type :: Type }
25 | TypeClassMemberResult { type :: Type
27 | TypeClassMemberResult { type :: Type
26 , typeClass :: QualifiedName
28 , typeClass :: QualifiedName
27 , typeClassArguments :: Array TypeArgument }
29 , typeClassArguments :: Array TypeArgument }
@@ -56,12 +58,12 @@ typeOf _ = Nothing
56-- | Common metadata for all types of search results.
58-- | Common metadata for all types of search results.
57newtype SearchResult
59newtype SearchResult
58 = SearchResult
60 = SearchResult
59− { name :: String
61+ { name :: Identifier
60 , comments :: Maybe String
62 , comments :: Maybe String
61 , hashAnchor :: String
63 , hashAnchor :: String
62− , moduleName :: String
64+ , moduleName :: ModuleName
63− , packageName :: String
65+ , packageInfo :: PackageInfo
64− , score :: Int
66+ , score :: PackageScore
65 , sourceSpan :: Maybe { start :: Array Int
67 , sourceSpan :: Maybe { start :: Array Int
66 , end :: Array Int
68 , end :: Array Int
67 , name :: String
69 , name :: String
src/Docs/Search/TypeDecoder.purs+46−78
@@ -1,18 +1,21 @@
1+-- | A decoder for types located in 'Language.PureScript.Types'.
1module Docs.Search.TypeDecoder where
2module Docs.Search.TypeDecoder where
2
3
3−import Prelude
4+import Docs.Search.Types (Identifier)
4
5
6+import Prelude
7+import Prim hiding (Type, Constraint)
5import Control.Alt ((<|>))
8import Control.Alt ((<|>))
6import Data.Argonaut.Core (Json, caseJsonObject, fromArray, fromObject, jsonEmptyObject, stringify, toArray)
9import Data.Argonaut.Core (Json, caseJsonObject, fromArray, fromObject, jsonEmptyObject, stringify, toArray)
7import Data.Argonaut.Decode (class DecodeJson, decodeJson, (.:))
10import Data.Argonaut.Decode (class DecodeJson, decodeJson, (.:))
8import Data.Argonaut.Encode (class EncodeJson, encodeJson)
11import Data.Argonaut.Encode (class EncodeJson, encodeJson)
9−import Data.Array ((!!))
12+import Data.Argonaut.Decode.Error (JsonDecodeError(..))
10import Data.Either (Either(..))
13import Data.Either (Either(..))
11import Data.Generic.Rep (class Generic)
14import Data.Generic.Rep (class Generic)
12−import Data.Generic.Rep.Show (genericShow)
15+import Data.Show.Generic (genericShow)
13import Data.List (List(..), (:))
16import Data.List (List(..), (:))
14import Data.List as List
17import Data.List as List
15−import Data.Maybe (Maybe(..), fromMaybe)
18+import Data.Maybe (Maybe(..))
16import Data.Newtype (class Newtype)
19import Data.Newtype (class Newtype)
17import Data.Tuple (Tuple(..))
20import Data.Tuple (Tuple(..))
18import Foreign.Object as Object
21import Foreign.Object as Object
@@ -25,71 +28,28 @@ instance showQualifiedName :: Show QualifiedName where
25 show = genericShow
28 show = genericShow
26
29
27newtype QualifiedName
30newtype QualifiedName
28− = QualifiedName { moduleName :: Array String
31+ = QualifiedName { moduleNameParts :: Array String
29− , name :: String
32+ , name :: Identifier
30 }
33 }
31
34
32instance decodeJsonQualifiedName :: DecodeJson QualifiedName where
35instance decodeJsonQualifiedName :: DecodeJson QualifiedName where
33 decodeJson json = do
36 decodeJson json = do
34 decodeTuple
37 decodeTuple
35− (\moduleName name -> QualifiedName { moduleName, name })
38+ (\moduleNameParts name -> QualifiedName { moduleNameParts, name })
36 (mkJsonError "QualifiedName" json)
39 (mkJsonError "QualifiedName" json)
37 json
40 json
38
41
39instance encodeJsonQualifiedName :: EncodeJson QualifiedName where
42instance encodeJsonQualifiedName :: EncodeJson QualifiedName where
40− encodeJson (QualifiedName { moduleName, name }) =
43+ encodeJson (QualifiedName { moduleNameParts, name }) =
41− encodeTuple moduleName name
44+ encodeTuple moduleNameParts name
42
45
43−mkJsonError :: String -> Json -> (forall i. i -> String)
46+mkJsonError :: String -> Json -> (forall i. i -> JsonDecodeError)
44mkJsonError name json _ =
47mkJsonError name json _ =
45− "Couldn't parse " <> name <> " from " <> stringify json
48+ TypeMismatch $ "Couldn't parse " <> name <> " from " <> stringify json
46
49
47−mkJsonError' :: String -> Json -> String
50+mkJsonError' :: String -> Json -> JsonDecodeError
48mkJsonError' name json = mkJsonError name json unit
51mkJsonError' name json = mkJsonError name json unit
49
52
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−
93-- | A typeclass constraint
53-- | A typeclass constraint
94newtype Constraint = Constraint
54newtype Constraint = Constraint
95 { constraintClass :: QualifiedName
55 { constraintClass :: QualifiedName
@@ -138,8 +98,10 @@ data Type
138 | TypeOp QualifiedName
98 | TypeOp QualifiedName
139 -- | A type application
99 -- | A type application
140 | TypeApp Type Type
100 | TypeApp Type Type
101+ -- | Explicit kind application
102+ | KindApp Type Type
141 -- | Forall quantifier
103 -- | Forall quantifier
142− | ForAll String (Maybe Kind) Type
104+ | ForAll String (Maybe Type) Type
143 -- | A type withset of type class constraints
105 -- | A type withset of type class constraints
144 | ConstrainedType Constraint Type
106 | ConstrainedType Constraint Type
145 {-
107 {-
@@ -149,11 +111,9 @@ data Type
149 -- | An empty row
111 -- | An empty row
150 | REmpty
112 | REmpty
151 -- | A non-empty row
113 -- | A non-empty row
152− | RCons String Type Type
114+ | RCons Identifier Type Type
153− {-
154 -- | A type with a kind annotation
115 -- | A type with a kind annotation
155− | Kinded Type Kind
116+ | Kinded Type Type
156− -}
157 -- | Binary operator application. During the rebracketing phase of desugaring,
117 -- | Binary operator application. During the rebracketing phase of desugaring,
158 -- this data constructor will be removed.
118 -- this data constructor will be removed.
159 | BinaryNoParensType Type Type Type
119 | BinaryNoParensType Type Type Type
@@ -179,6 +139,9 @@ instance decodeJsonType :: DecodeJson Type where
179 "TypeApp" ->
139 "TypeApp" ->
180 decodeContents (decodeTuple TypeApp (const err)) (Left err) json
140 decodeContents (decodeTuple TypeApp (const err)) (Left err) json
181 where err = mkJsonError' "TypeApp" json
141 where err = mkJsonError' "TypeApp" json
142+ "KindApp" ->
143+ decodeContents (decodeTuple KindApp (const err)) (Left err) json
144+ where err = mkJsonError' "KindApp" json
182 "ForAll" ->
145 "ForAll" ->
183 decodeContents
146 decodeContents
184 (decodeTriple
147 (decodeTriple
@@ -187,9 +150,10 @@ instance decodeJsonType :: DecodeJson Type where
187 (Left $ err unit)
150 (Left $ err unit)
188 json
151 json
189 <|>
152 <|>
153+ -- Ignore SkolemScope
190 decodeContents
154 decodeContents
191 (decodeQuadriple
155 (decodeQuadriple
192− (\f (k :: Kind) a (_ :: Maybe Int) ->
156+ (\f (k :: Type) a (_ :: Maybe Int) ->
193 ForAll f (Just k) a)
157 ForAll f (Just k) a)
194 err)
158 err)
195 (Left $ err unit)
159 (Left $ err unit)
@@ -202,6 +166,9 @@ instance decodeJsonType :: DecodeJson Type where
202 "RCons" ->
166 "RCons" ->
203 decodeContents (decodeTriple RCons (const err)) (Left err) json
167 decodeContents (decodeTriple RCons (const err)) (Left err) json
204 where err = mkJsonError' "RCons" json
168 where err = mkJsonError' "RCons" json
169+ "KindedType" ->
170+ decodeContents (decodeTuple Kinded (const err)) (Left err) json
171+ where err = mkJsonError' "KindedType" json
205 "BinaryNoParensType" ->
172 "BinaryNoParensType" ->
206 decodeContents (decodeTriple BinaryNoParensType (const err)) (Left err) json
173 decodeContents (decodeTriple BinaryNoParensType (const err)) (Left err) json
207 where err = mkJsonError' "BinaryNoParens" json
174 where err = mkJsonError' "BinaryNoParens" json
@@ -219,11 +186,13 @@ instance encodeJsonType :: EncodeJson Type where
219 TypeConstructor val -> tagged "TypeConstructor" (encodeJson val)
186 TypeConstructor val -> tagged "TypeConstructor" (encodeJson val)
220 TypeOp val -> tagged "TypeOp" (encodeJson val)
187 TypeOp val -> tagged "TypeOp" (encodeJson val)
221 TypeApp t1 t2 -> tagged "TypeApp" (encodeTuple t1 t2)
188 TypeApp t1 t2 -> tagged "TypeApp" (encodeTuple t1 t2)
189+ KindApp t1 t2 -> tagged "KindApp" (encodeTuple t1 t2)
222 ForAll str Nothing ty -> tagged "ForAll" (encodeTriple str ty emptySkolemScope)
190 ForAll str Nothing ty -> tagged "ForAll" (encodeTriple str ty emptySkolemScope)
223 ForAll str (Just k) ty -> tagged "ForAll" (encodeQuadriple str k ty emptySkolemScope)
191 ForAll str (Just k) ty -> tagged "ForAll" (encodeQuadriple str k ty emptySkolemScope)
224 ConstrainedType c t -> tagged "ConstrainedType" (encodeTuple c t)
192 ConstrainedType c t -> tagged "ConstrainedType" (encodeTuple c t)
225 REmpty -> tagged "REmpty" jsonEmptyObject
193 REmpty -> tagged "REmpty" jsonEmptyObject
226 RCons s t1 t2 -> tagged "RCons" (encodeTriple s t1 t2)
194 RCons s t1 t2 -> tagged "RCons" (encodeTriple s t1 t2)
195+ Kinded t1 t2 -> tagged "KindedType" (encodeTuple t1 t2)
227 ParensInType t -> tagged "ParensInType" (encodeJson t)
196 ParensInType t -> tagged "ParensInType" (encodeJson t)
228 TypeWildcard -> tagged "TypeWildcard" jsonEmptyObject
197 TypeWildcard -> tagged "TypeWildcard" jsonEmptyObject
229 BinaryNoParensType t1 t2 t3 ->
198 BinaryNoParensType t1 t2 t3 ->
@@ -268,7 +237,7 @@ instance encodeJsonFunDeps :: EncodeJson FunDeps where
268newtype TypeArgument
237newtype TypeArgument
269 = TypeArgument
238 = TypeArgument
270 { name :: String
239 { name :: String
271− , mbKind :: Maybe Kind
240+ , mbKind :: Maybe Type
272 }
241 }
273
242
274derive newtype instance eqTypeArgument :: Eq TypeArgument
243derive newtype instance eqTypeArgument :: Eq TypeArgument
@@ -292,17 +261,16 @@ decodeTuple
292 . DecodeJson fst
261 . DecodeJson fst
293 => DecodeJson sec
262 => DecodeJson sec
294 => (fst -> sec -> res)
263 => (fst -> sec -> res)
295− -> (forall a. a -> String)
264+ -> (forall a. a -> JsonDecodeError)
296 -> Json
265 -> Json
297− -> Either String res
266+ -> Either JsonDecodeError res
298decodeTuple cont err json =
267decodeTuple cont err json =
299− fromMaybe (Left $ err unit) $
300− toArray json >>= \jsons ->
268+ case toArray json of
301− jsons !! 0 >>= \json1 ->
269+ Just [ json1, json2 ] -> do
302− jsons !! 1 >>= \json2 -> pure $ do
303− fst <- decodeJson json1
270+ fst <- decodeJson json1
304− sec <- decodeJson json2
271+ sec <- decodeJson json2
305− pure $ cont fst sec
272+ pure $ cont fst sec
273+ _ -> Left $ err unit
306
274
307-- | Decode a heterogeneous triple.
275-- | Decode a heterogeneous triple.
308decodeTriple
276decodeTriple
@@ -311,9 +279,9 @@ decodeTriple
311 => DecodeJson sec
279 => DecodeJson sec
312 => DecodeJson trd
280 => DecodeJson trd
313 => (fst -> sec -> trd -> res)
281 => (fst -> sec -> trd -> res)
314− -> (forall a. a -> String)
282+ -> (forall a. a -> JsonDecodeError)
315 -> Json
283 -> Json
316− -> Either String res
284+ -> Either JsonDecodeError res
317decodeTriple cont err json =
285decodeTriple cont err json =
318 case toArray json of
286 case toArray json of
319 Just [ json1, json2, json3 ] -> do
287 Just [ json1, json2, json3 ] -> do
@@ -331,9 +299,9 @@ decodeQuadriple
331 => DecodeJson trd
299 => DecodeJson trd
332 => DecodeJson frt
300 => DecodeJson frt
333 => (fst -> sec -> trd -> frt -> res)
301 => (fst -> sec -> trd -> frt -> res)
334− -> (forall a. a -> String)
302+ -> (forall a. a -> JsonDecodeError)
335 -> Json
303 -> Json
336− -> Either String res
304+ -> Either JsonDecodeError res
337decodeQuadriple cont err json =
305decodeQuadriple cont err json =
338 case toArray json of
306 case toArray json of
339 Just [ json1, json2, json3, json4 ] -> do
307 Just [ json1, json2, json3, json4 ] -> do
@@ -403,7 +371,7 @@ tagged tag contents =
403joinForAlls
371joinForAlls
404 :: Type
372 :: Type
405 -> { binders :: List { name :: String
373 -> { binders :: List { name :: String
406− , mbKind :: Maybe Kind }
374+ , mbKind :: Maybe Type }
407 , ty :: Type
375 , ty :: Type
408 }
376 }
409joinForAlls ty = go Nil ty
377joinForAlls ty = go Nil ty
@@ -412,7 +380,7 @@ joinForAlls ty = go Nil ty
412 go ({ name, mbKind } : acc) ty'
380 go ({ name, mbKind } : acc) ty'
413 go acc ty' = { binders: acc, ty: ty' }
381 go acc ty' = { binders: acc, ty: ty' }
414
382
415−joinRows :: Type -> { rows :: List { row :: String
383+joinRows :: Type -> { rows :: List { row :: Identifier
416 , ty :: Type
384 , ty :: Type
417 }
385 }
418 , ty :: Maybe Type }
386 , ty :: Maybe Type }
@@ -428,7 +396,7 @@ joinRows = go Nil
428 }
396 }
429
397
430-- | Only returns a list of type class names (lists of arguments are omitted).
398-- | 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
432 , ty :: Type }
400 , ty :: Type }
433joinConstraints = go Nil
401joinConstraints = go Nil
434 where
402 where
src/Docs/Search/TypeIndex.js+1−1
@@ -1,6 +1,6 @@
1/* global exports */
1/* global exports */
2
2
3−exports.lookup_ = function (shape) {
3+export function lookup_ (shape) {
4 return function (url) {
4 return function (url) {
5 return function () {
5 return function () {
6 return new Promise(function (resolve, reject) {
6 return new Promise(function (resolve, reject) {
src/Docs/Search/TypeIndex.purs+11−10
@@ -1,40 +1,40 @@
1-- | Partial type index, can be loaded on demand in the browser.
1-- | Partial type index, can be loaded on demand in the browser.
2module Docs.Search.TypeIndex where
2module Docs.Search.TypeIndex where
3
3
4−import Docs.Search.Config (config)
4+import Docs.Search.Config as Config
5import Docs.Search.Declarations (resultsForDeclaration)
5import Docs.Search.Declarations (resultsForDeclaration)
6import Docs.Search.DocsJson (DocsJson(..))
6import Docs.Search.DocsJson (DocsJson(..))
7import Docs.Search.Score (Scores)
7import Docs.Search.Score (Scores)
8import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
8import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..))
9import Docs.Search.TypeDecoder (Type)
9import Docs.Search.TypeDecoder (Type)
10import Docs.Search.TypeQuery (TypeQuery)
10import Docs.Search.TypeQuery (TypeQuery)
11+import Docs.Search.Types (ModuleName(..))
11import Docs.Search.TypeShape (shapeOfType, shapeOfTypeQuery, stringifyShape)
12import Docs.Search.TypeShape (shapeOfType, shapeOfTypeQuery, stringifyShape)
12
13
13import Prelude
14import Prelude
14−
15+import Prim hiding (Type)
15import Control.Promise (Promise, toAffE)
16import Control.Promise (Promise, toAffE)
16import Data.Argonaut.Core (Json)
17import Data.Argonaut.Core (Json)
17import Data.Argonaut.Decode (decodeJson)
18import Data.Argonaut.Decode (decodeJson)
18import Data.Array as Array
19import Data.Array as Array
19import Data.Either (hush)
20import Data.Either (hush)
21+import Data.Foldable (fold, foldr)
20import Data.Map (Map)
22import Data.Map (Map)
21import Data.Map as Map
23import Data.Map as Map
22import Data.Maybe (Maybe(..), fromMaybe', isJust)
24import Data.Maybe (Maybe(..), fromMaybe', isJust)
23−import Data.Newtype (class Newtype, unwrap, wrap)
25+import Data.Newtype (class Newtype, over)
24import Effect (Effect)
26import Effect (Effect)
25import Effect.Aff (Aff, try)
27import Effect.Aff (Aff, try)
26
28
27
29
28newtype TypeIndex = TypeIndex (Map String (Maybe (Array SearchResult)))
30newtype TypeIndex = TypeIndex (Map String (Maybe (Array SearchResult)))
29
31
30−derive newtype instance semigroupTypeIndex :: Semigroup TypeIndex
31−derive newtype instance monoidTypeIndex :: Monoid TypeIndex
32derive instance newtypeTypeIndex :: Newtype TypeIndex _
32derive instance newtypeTypeIndex :: Newtype TypeIndex _
33
33
34
34
35mkTypeIndex :: Scores -> Array DocsJson -> TypeIndex
35mkTypeIndex :: Scores -> Array DocsJson -> TypeIndex
36mkTypeIndex scores docsJsons =
36mkTypeIndex scores docsJsons =
37− TypeIndex $ map Just $ Array.foldr insert mempty docsJsons
37+ TypeIndex $ map Just $ foldr insert Map.empty docsJsons
38 where
38 where
39 insert :: DocsJson -> Map String (Array SearchResult) -> Map String (Array SearchResult)
39 insert :: DocsJson -> Map String (Array SearchResult) -> Map String (Array SearchResult)
40 insert docsJson mp =
40 insert docsJson mp =
@@ -48,7 +48,8 @@ mkTypeIndex scores docsJsons =
48
48
49allResults :: Scores -> DocsJson -> Array SearchResult
49allResults :: Scores -> DocsJson -> Array SearchResult
50allResults scores (DocsJson { name, declarations }) =
50allResults scores (DocsJson { name, declarations }) =
51− declarations >>= (resultsForDeclaration scores name >>> map (_.result) >>> Array.fromFoldable)
51+ declarations >>= (resultsForDeclaration scores (ModuleName name) >>>
52+ map (_.result) >>> Array.fromFoldable)
52
53
53
54
54resultsWithTypes :: Scores -> DocsJson -> Array SearchResult
55resultsWithTypes :: Scores -> DocsJson -> Array SearchResult
@@ -76,9 +77,9 @@ lookup
76 -> Aff { index :: TypeIndex, results :: Array SearchResult }
77 -> Aff { index :: TypeIndex, results :: Array SearchResult }
77lookup key index@(TypeIndex map) =
78lookup key index@(TypeIndex map) =
78 case Map.lookup key map of
79 case Map.lookup key map of
79− Just results -> pure { index, results: Array.fold results }
80+ Just results -> pure { index, results: fold results }
80 Nothing -> do
81 Nothing -> do
81− eiJson <- try (toAffE (lookup_ key $ config.mkShapeScriptPath key))
82+ eiJson <- try (toAffE (lookup_ key $ Config.mkShapeScriptPath key))
82 pure $ fromMaybe'
83 pure $ fromMaybe'
83 (\_ -> { index: insert key Nothing index, results: [] })
84 (\_ -> { index: insert key Nothing index, results: [] })
84 do
85 do
@@ -92,7 +93,7 @@ lookup key index@(TypeIndex map) =
92 -> Maybe (Array SearchResult)
93 -> Maybe (Array SearchResult)
93 -> TypeIndex
94 -> TypeIndex
94 -> TypeIndex
95 -> TypeIndex
95− insert k v = unwrap >>> Map.insert k v >>> wrap
96+ insert k v = over TypeIndex (Map.insert k v)
96
97
97
98
98query
99query
src/Docs/Search/TypePrinter.purs+19−21
@@ -1,14 +1,16 @@
1module Docs.Search.TypePrinter where
1module Docs.Search.TypePrinter where
2
2
3import Prelude
3import Prelude
4−
4+import Prim hiding (Type, Constraint)
5import Docs.Search.Extra ((>#>))
5import Docs.Search.Extra ((>#>))
6import Docs.Search.Terminal (cyan)
6import 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(..))
8
9
9−import Data.Maybe (Maybe(..), fromMaybe)
10import Data.Array as Array
10import Data.Array as Array
11import Data.List as List
11import Data.List as List
12+import Data.Maybe (Maybe(..), fromMaybe)
13+import Data.Newtype (unwrap)
12
14
13
15
14-- | A pretty-printer for types, for TTY with colors.
16-- | A pretty-printer for types, for TTY with colors.
@@ -21,20 +23,23 @@ showType = case _ of
21 TypeOp qname -> showQualifiedName qname
23 TypeOp qname -> showQualifiedName qname
22
24
23 TypeApp (TypeApp (TypeConstructor
25 TypeApp (TypeApp (TypeConstructor
24− (QualifiedName { moduleName: [ "Prim" ]
26+ (QualifiedName { moduleNameParts: [ "Prim" ]
25− , name: "Function" }))
27+ , name: Identifier "Function" }))
26 t1)
28 t1)
27 t2 ->
29 t2 ->
28 showType t1 <> syntax " -> " <> showType t2
30 showType t1 <> syntax " -> " <> showType t2
29
31
30− TypeApp (TypeConstructor (QualifiedName { moduleName: [ "Prim" ]
32+ TypeApp (TypeConstructor (QualifiedName { moduleNameParts: [ "Prim" ]
31− , name: "Record" }))
33+ , name: Identifier "Record" }))
32 row ->
34 row ->
33 showRow false row
35 showRow false row
34
36
35 TypeApp t1 t2 ->
37 TypeApp t1 t2 ->
36 showType t1 <> " " <> showType t2
38 showType t1 <> " " <> showType t2
37
39
40+ KindApp t1 t2 ->
41+ showType t1 <> " " <> showType t2
42+
38 ty@(ForAll _ _ _) ->
43 ty@(ForAll _ _ _) ->
39 showForAll ty
44 showForAll ty
40
45
@@ -46,6 +51,8 @@ showType = case _ of
46 ty@REmpty -> showRow true ty
51 ty@REmpty -> showRow true ty
47 ty@(RCons _ _ _) -> showRow true ty
52 ty@(RCons _ _ _) -> showRow true ty
48
53
54+ Kinded t1 t2 -> showType t1 <> " :: " <> showType t2
55+
49 BinaryNoParensType op t1 t2 ->
56 BinaryNoParensType op t1 t2 ->
50 showType t1 <>
57 showType t1 <>
51 space <>
58 space <>
@@ -68,7 +75,7 @@ showTypeArgument (TypeArgument { name, mbKind }) =
68 "(" <>
75 "(" <>
69 name <>
76 name <>
70 " :: " <>
77 " :: " <>
71− showKind kind <>
78+ showType kind <>
72 ")"
79 ")"
73
80
74
81
@@ -89,7 +96,7 @@ showQualifiedName
89 :: QualifiedName
96 :: QualifiedName
90 -> String
97 -> String
91showQualifiedName (QualifiedName { name })
98showQualifiedName (QualifiedName { name })
92− = name
99+ = unwrap name
93
100
94
101
95showRow
102showRow
@@ -107,7 +114,7 @@ showRow asRow =
107 opening <>
114 opening <>
108 ( Array.intercalate ", " $ Array.fromFoldable $ rows <#>
115 ( Array.intercalate ", " $ Array.fromFoldable $ rows <#>
109 \entry ->
116 \entry ->
110− entry.row <> syntax " :: " <> showType entry.ty
117+ unwrap entry.row <> syntax " :: " <> showType entry.ty
111 ) <>
118 ) <>
112
119
113 (ty >#> \ty' -> " | " <> showType ty') <>
120 (ty >#> \ty' -> " | " <> showType ty') <>
@@ -125,7 +132,7 @@ showForAll
125showForAll ty =
132showForAll ty =
126 keyword "forall" <>
133 keyword "forall" <>
127
134
128− ( Array.fold $ foralls.binders <#>
135+ ( Array.fold $ Array.fromFoldable $ foralls.binders <#>
129 \ { name, mbKind } ->
136 \ { name, mbKind } ->
130 case mbKind of
137 case mbKind of
131 Nothing -> " " <> name
138 Nothing -> " " <> name
@@ -133,7 +140,7 @@ showForAll ty =
133 " (" <> name <> " "
140 " (" <> name <> " "
134 <> syntax "::"
141 <> syntax "::"
135 <> space
142 <> space
136− <> showKind kind
143+ <> showType kind
137 <> ")"
144 <> ")"
138 ) <>
145 ) <>
139
146
@@ -144,15 +151,6 @@ showForAll ty =
144 foralls = joinForAlls ty
151 foralls = joinForAlls ty
145
152
146
153
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−
156showConstraint
154showConstraint
157 :: Constraint
155 :: Constraint
158 -> String
156 -> String
src/Docs/Search/TypeQuery.purs+65−51
@@ -10,17 +10,18 @@ module Docs.Search.TypeQuery
10 )
10 )
11where
11where
12
12
13−import Docs.Search.Config (config)
13+import Docs.Search.Config as Config
14import Docs.Search.Extra (foldl1, foldr1)
14import Docs.Search.Extra (foldl1, foldr1)
15import Docs.Search.TypeDecoder (QualifiedName(..), Type(..), joinConstraints, joinRows)
15import Docs.Search.TypeDecoder (QualifiedName(..), Type(..), joinConstraints, joinRows)
16+import Docs.Search.Types (Identifier(..))
16
17
17import Prelude
18import Prelude
18−
19+import Prim hiding (Type)
19import Control.Alt ((<|>))
20import Control.Alt ((<|>))
20import Data.Array as Array
21import Data.Array as Array
21import Data.Either (Either)
22import Data.Either (Either)
22import Data.Generic.Rep (class Generic)
23import Data.Generic.Rep (class Generic)
23−import Data.Generic.Rep.Show (genericShow)
24+import Data.Show.Generic (genericShow)
24import Data.List (List(..), many, some, (:))
25import Data.List (List(..), many, some, (:))
25import Data.List as List
26import Data.List as List
26import Data.List.NonEmpty (NonEmptyList)
27import Data.List.NonEmpty (NonEmptyList)
@@ -33,21 +34,21 @@ import Data.Set as Set
33import Data.String.CodeUnits (fromCharArray)
34import Data.String.CodeUnits (fromCharArray)
34import Data.String.Common (trim) as String
35import Data.String.Common (trim) as String
35import Data.Tuple (Tuple(..), fst, snd)
36import Data.Tuple (Tuple(..), fst, snd)
36−import Text.Parsing.StringParser (ParseError, Parser, runParser, try)
37+import StringParser (ParseError, Parser, runParser, try)
37−import Text.Parsing.StringParser.CodePoints (alphaNum, anyLetter, char, eof, lowerCaseChar, skipSpaces, string, upperCaseChar)
38+import StringParser.CodePoints (alphaNum, anyLetter, char, eof, lowerCaseChar, skipSpaces, string, upperCaseChar)
38−import Text.Parsing.StringParser.Combinators (fix, sepBy, sepBy1, sepEndBy, sepEndBy1)
39+import StringParser.Combinators (fix, sepBy, sepBy1, sepEndBy, sepEndBy1)
39
40
40
41
41-- | We need type queries because we don't have a full-featured type parser
42-- | We need type queries because we don't have a full-featured type parser
42-- | available.
43-- | available.
43data TypeQuery
44data TypeQuery
44− = QVar String
45+ = QVar Identifier
45− | QConst String
46+ | QConst Identifier
46 | QFun TypeQuery TypeQuery
47 | QFun TypeQuery TypeQuery
47 | QApp TypeQuery TypeQuery
48 | QApp TypeQuery TypeQuery
48− | QForAll (NonEmptyList String) TypeQuery
49+ | QForAll (NonEmptyList Identifier) TypeQuery
49− | QConstraint String (List TypeQuery) TypeQuery
50+ | QConstraint Identifier (List TypeQuery) TypeQuery
50− | QRow (List (Tuple String TypeQuery))
51+ | QRow (List (Tuple Identifier TypeQuery))
51
52
52derive instance eqTypeQuery :: Eq TypeQuery
53derive instance eqTypeQuery :: Eq TypeQuery
53derive instance genericTypeQuery :: Generic TypeQuery _
54derive instance genericTypeQuery :: Generic TypeQuery _
@@ -69,7 +70,8 @@ typeQueryParser = fix \typeQuery ->
69
70
70 row = string "(" *> rowFields <* string ")"
71 row = string "(" *> rowFields <* string ")"
71
72
73+ record = QApp (QConst $ Identifier "Record") <$>
72− record = QApp (QConst "Record") <$> (string "{" *> rowFields <* string "}")
74+ (string "{" *> rowFields <* string "}")
73
75
74 binders =
76 binders =
75 string "forall" *> some space *> sepEndBy1 ident skipSpaces <* string "." <* skipSpaces
77 string "forall" *> some space *> sepEndBy1 ident skipSpaces <* string "." <* skipSpaces
@@ -111,32 +113,32 @@ concrete :: Parser TypeQuery
111concrete =
113concrete =
112 QConst <$> upperCaseIdent
114 QConst <$> upperCaseIdent
113
115
114−ident :: Parser String
116+ident :: Parser Identifier
115ident = do
117ident = do
116 head <- anyLetter
118 head <- anyLetter
117 rest <- Array.many (alphaNum <|> char '\'')
119 rest <- Array.many (alphaNum <|> char '\'')
118− pure $ fromCharArray $ pure head <> rest
120+ pure $ Identifier <$> fromCharArray $ pure head <> rest
119
121
120−upperCaseIdent :: Parser String
122+upperCaseIdent :: Parser Identifier
121upperCaseIdent = do
123upperCaseIdent = do
122 head <- upperCaseChar
124 head <- upperCaseChar
123 rest <- Array.many (alphaNum <|> char '\'')
125 rest <- Array.many (alphaNum <|> char '\'')
124− pure $ fromCharArray $ pure head <> rest
126+ pure $ Identifier $ fromCharArray $ pure head <> rest
125
127
126−lowerCaseIdent :: Parser String
128+lowerCaseIdent :: Parser Identifier
127lowerCaseIdent = do
129lowerCaseIdent = do
128 head <- lowerCaseChar
130 head <- lowerCaseChar
129 rest <- Array.many (alphaNum <|> char '\'')
131 rest <- Array.many (alphaNum <|> char '\'')
130− pure $ fromCharArray $ pure head <> rest
132+ pure $ Identifier $ fromCharArray $ pure head <> rest
131
133
132space :: Parser Char
134space :: Parser Char
133space = char ' '
135space = char ' '
134
136
135
137
136-- | Used only in `getFreeVariables`.
138-- | Used only in `getFreeVariables`.
137−data FreeVarCounterQueueEntry = Unbind (Set.Set String) | Next TypeQuery
139+data FreeVarCounterQueueEntry = Unbind (Set.Set Identifier) | Next TypeQuery
138
140
139−getFreeVariables :: TypeQuery -> Set.Set String
141+getFreeVariables :: TypeQuery -> Set.Set Identifier
140getFreeVariables query = go Set.empty Set.empty (List.singleton $ Next query)
142getFreeVariables query = go Set.empty Set.empty (List.singleton $ Next query)
141 where
143 where
142 insertIfUnbound bound var free =
144 insertIfUnbound bound var free =
@@ -172,11 +174,11 @@ getFreeVariables query = go Set.empty Set.empty (List.singleton $ Next query)
172
174
173
175
174data Substitution
176data Substitution
175− = Instantiate String Type
177+ = Instantiate Identifier Type
176− | Match String String
178+ | Match Identifier Identifier
177− | Generalize TypeQuery String
179+ | Generalize TypeQuery Identifier
178− | Substitute String String
180+ | Substitute Identifier Identifier
179− | MatchConstraints (Set String) (Set String)
181+ | MatchConstraints (Set Identifier) (Set Identifier)
180 | MissingConstraint
182 | MissingConstraint
181 | ExcessiveConstraint
183 | ExcessiveConstraint
182 | RowsMismatch Int Int
184 | RowsMismatch Int Int
@@ -225,22 +227,22 @@ unify query type_ = go Nil (List.singleton { q: query, t: type_ })
225
227
226 -- * Type variables
228 -- * Type variables
227 go acc ({ q: QVar q, t: TypeVar v } : rest) =
229 go acc ({ q: QVar q, t: TypeVar v } : rest) =
228− go (Substitute q v : acc) rest
230+ go (Substitute q (Identifier v) : acc) rest
229 go acc ({ q, t: TypeVar v } : rest ) =
231 go acc ({ q, t: TypeVar v } : rest ) =
230− go (Generalize q v : acc) rest
232+ go (Generalize q (Identifier v) : acc) rest
231 go acc ({ q: QVar v, t } : rest) =
233 go acc ({ q: QVar v, t } : rest) =
232 go (Instantiate v t : acc) rest
234 go (Instantiate v t : acc) rest
233
235
234 -- * Names
236 -- * Names
235 go acc ({ q: QConst qname, t: TypeConstructor (QualifiedName { name }) } : rest) =
237 go acc ({ q: QConst qname, t: TypeConstructor (QualifiedName { name }) } : rest) =
236 go (Match qname name : acc) rest
238 go (Match qname name : acc) rest
237− go acc ({ q: QConst qname, t } : rest) =
239+ go acc ({ q: QConst _, t } : rest) =
238 go (TypeMismatch t : acc) rest
240 go (TypeMismatch t : acc) rest
239− go acc ({ q, t: TypeConstructor (QualifiedName { name }) } : rest) =
241+ go acc ({ q, t: TypeConstructor (QualifiedName _) } : rest) =
240 go (QueryMismatch q : acc) rest
242 go (QueryMismatch q : acc) rest
241
243
242 -- type operators can't appear in type queries: this is always a mismatch
244 -- 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) =
244 go (QueryMismatch q : acc) rest
246 go (QueryMismatch q : acc) rest
245 go acc ({ q, t: t@(BinaryNoParensType _ _ _) } : rest) =
247 go acc ({ q, t: t@(BinaryNoParensType _ _ _) } : rest) =
246 go (Mismatch q t : acc) rest
248 go (Mismatch q t : acc) rest
@@ -248,18 +250,18 @@ unify query type_ = go Nil (List.singleton { q: query, t: type_ })
248 -- * Functions
250 -- * Functions
249 go acc ({ q: QFun q1 q2
251 go acc ({ q: QFun q1 q2
250 , t: TypeApp (TypeApp (TypeConstructor
252 , t: TypeApp (TypeApp (TypeConstructor
251− (QualifiedName { moduleName: [ "Prim" ]
253+ (QualifiedName { moduleNameParts: [ "Prim" ]
252− , name: "Function" })) t1) t2 } : rest) =
254+ , name: Identifier "Function" })) t1) t2 } : rest) =
253 go acc ({ q: q1, t: t1 } : { q: q2, t: t2 } : rest)
255 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) =
255 go (Mismatch q t : acc) rest
257 go (Mismatch q t : acc) rest
256
258
257 -- * Rows
259 -- * Rows
258− go acc ({ q: QApp (QConst "Record") (QRow qRows)
260+ go acc ({ q: QApp (QConst (Identifier "Record")) (QRow qRows)
259 , t: TypeApp (TypeConstructor
261 , t: TypeApp (TypeConstructor
260− (QualifiedName { moduleName: [ "Prim" ]
262+ (QualifiedName { moduleNameParts: [ "Prim" ]
261− , name: "Record" })) row } : rest) =
263+ , name: Identifier "Record" })) row } : rest) =
262− let { rows, ty } = joinRows row
264+ let { rows } = joinRows row
263 qRowsLength = List.length qRows
265 qRowsLength = List.length qRows
264 rowsLength = List.length rows in
266 rowsLength = List.length rows in
265 if rowsLength == qRowsLength then
267 if rowsLength == qRowsLength then
@@ -295,12 +297,18 @@ unify query type_ = go Nil (List.singleton { q: query, t: type_ })
295 go acc ({ q, t: REmpty } : rest) =
297 go acc ({ q, t: REmpty } : rest) =
296 go (QueryMismatch q : acc) rest
298 go (QueryMismatch q : acc) rest
297
299
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+
298
306
299-- | Sum various penalties.
307-- | Sum various penalties.
300penalty :: TypeQuery -> Type -> Int
308penalty :: TypeQuery -> Type -> Int
301penalty typeQuery ty =
309penalty typeQuery ty =
302 let substs = unify typeQuery ty in
310 let substs = unify typeQuery ty in
303− typeVarPenalty substs * config.penalties.typeVars +
311+ typeVarPenalty substs * Config.penalties.typeVars +
304 namesPenalty substs +
312 namesPenalty substs +
305 mismatchPenalty substs
313 mismatchPenalty substs
306
314
@@ -319,14 +327,17 @@ typeVarPenalty substs =
319 insertion v1 v2 = Map.insertWith append v1 (Set.singleton v2)
327 insertion v1 v2 = Map.insertWith append v1 (Set.singleton v2)
320
328
321 varSubstMapWith
329 varSubstMapWith
322− :: (String -> String -> Map String (Set String) -> Map String (Set String))
330+ :: (Identifier ->
323− -> Map String (Set String)
331+ Identifier ->
332+ Map Identifier (Set Identifier) ->
333+ Map Identifier (Set Identifier))
334+ -> Map Identifier (Set Identifier)
324 varSubstMapWith f =
335 varSubstMapWith f =
325 List.foldr (case _ of
336 List.foldr (case _ of
326 Substitute v1 v2 ->
337 Substitute v1 v2 ->
327 f v1 v2
338 f v1 v2
328 _ -> identity
339 _ -> identity
329− ) mempty substs
340+ ) Map.empty substs
330
341
331
342
332-- | Penalty for name mismatches.
343-- | Penalty for name mismatches.
@@ -336,12 +347,12 @@ namesPenalty = go 0
336 go p Nil = p
347 go p Nil = p
337 go p (Match a b : rest)
348 go p (Match a b : rest)
338 | a == b = go p rest
349 | a == b = go p rest
339− | otherwise = go (p + config.penalties.match) rest
350+ | otherwise = go (p + Config.penalties.match) rest
340 go p (MatchConstraints qcs tcs : rest)
351 go p (MatchConstraints qcs tcs : rest)
341 = let p' = Set.size (Set.union qcs tcs) -
352 = let p' = Set.size (Set.union qcs tcs) -
342 Set.size (Set.intersection qcs tcs) in
353 Set.size (Set.intersection qcs tcs) in
343− go (p + config.penalties.matchConstraint * p') rest
354+ go (p + Config.penalties.matchConstraint * p') rest
344− go p (RowsMismatch n m : rest) = go (config.penalties.rowsMismatch * abs (n - m)) rest
355+ go p (RowsMismatch n m : rest) = go (Config.penalties.rowsMismatch * abs (n - m)) rest
345 go p (_ : rest) = go p rest
356 go p (_ : rest) = go p rest
346
357
347
358
@@ -351,11 +362,11 @@ mismatchPenalty = go 0
351 where
362 where
352 go n Nil = n
363 go n Nil = n
353 go n (Instantiate q t : rest) = go (n + typeSize t *
364 go n (Instantiate q t : rest) = go (n + typeSize t *
354− config.penalties.instantiate) rest
365+ Config.penalties.instantiate) rest
355 go n (Generalize q t : rest) = go (n + typeQuerySize q *
366 go n (Generalize q t : rest) = go (n + typeQuerySize q *
356− config.penalties.generalize) rest
367+ Config.penalties.generalize) rest
357− go n (ExcessiveConstraint : rest) = go (n + config.penalties.excessiveConstraint) rest
368+ go n (ExcessiveConstraint : rest) = go (n + Config.penalties.excessiveConstraint) rest
358− go n (MissingConstraint : rest) = go (n + config.penalties.missingConstraint) rest
369+ go n (MissingConstraint : rest) = go (n + Config.penalties.missingConstraint) rest
359 go n (Mismatch q t : rest) = go (n + typeQuerySize q + typeSize t) rest
370 go n (Mismatch q t : rest) = go (n + typeQuerySize q + typeSize t) rest
360 go n (TypeMismatch t : rest) = go (n + typeSize t) rest
371 go n (TypeMismatch t : rest) = go (n + typeSize t) rest
361 go n (QueryMismatch q : rest) = go (n + typeQuerySize q) rest
372 go n (QueryMismatch q : rest) = go (n + typeQuerySize q) rest
@@ -363,7 +374,7 @@ mismatchPenalty = go 0
363
374
364
375
365-- | Only returns a list of type class names (lists of arguments are omitted).
376-- | 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
367 , ty :: TypeQuery }
378 , ty :: TypeQuery }
368joinQueryConstraints = go Nil
379joinQueryConstraints = go Nil
369 where
380 where
@@ -406,9 +417,10 @@ typeSize = go 0 <<< List.singleton
406 go (n + 1) rest
417 go (n + 1) rest
407 go n (TypeOp _ : rest) =
418 go n (TypeOp _ : rest) =
408 go (n + 1) rest
419 go (n + 1) rest
420+ go n (KindApp t1 t2 : res) = go n (t1 : t2 : res)
409 go n (TypeApp (TypeApp (TypeConstructor
421 go n (TypeApp (TypeApp (TypeConstructor
410− (QualifiedName { moduleName: [ "Prim" ]
422+ (QualifiedName { moduleNameParts: [ "Prim" ]
411− , name: "Function" })) t1) t2 : rest) =
423+ , name: Identifier "Function" })) t1) t2 : rest) =
412 go (n + 1) (t1 : t2 : rest)
424 go (n + 1) (t1 : t2 : rest)
413 go n (TypeApp q1 q2 : rest) =
425 go n (TypeApp q1 q2 : rest) =
414 go (n + 1) (q1 : q2 : rest)
426 go (n + 1) (q1 : q2 : rest)
@@ -420,6 +432,8 @@ typeSize = go 0 <<< List.singleton
420 go (n + 1) (t1 : t2 : rest)
432 go (n + 1) (t1 : t2 : rest)
421 go n (REmpty : rest) =
433 go n (REmpty : rest) =
422 go (n + 1) rest
434 go (n + 1) rest
435+ go n (Kinded t1 t2 : rest) =
436+ go n (t1 : t2 : rest)
423 go n (BinaryNoParensType op t1 t2 : rest) =
437 go n (BinaryNoParensType op t1 t2 : rest) =
424 go (n + 1) (t1 : t2 : rest)
438 go (n + 1) (t1 : t2 : rest)
425 go n (ParensInType t : rest) =
439 go n (ParensInType t : rest) =
src/Docs/Search/TypeShape.js+1−1
@@ -1,6 +1,6 @@
1/* global exports */
1/* global exports */
2
2
3−exports.hash = function (string) {
3+export function hash (string) {
4 var hash = Math.floor(Number.MAX_SAFE_INTEGER / 2);
4 var hash = Math.floor(Number.MAX_SAFE_INTEGER / 2);
5 if (string.length == 0) {
5 if (string.length == 0) {
6 return hash;
6 return hash;
src/Docs/Search/TypeShape.purs+10−4
@@ -5,11 +5,12 @@ module Docs.Search.TypeShape where
5
5
6import Docs.Search.TypeDecoder (QualifiedName(..), Type(..), joinForAlls, joinRows)
6import Docs.Search.TypeDecoder (QualifiedName(..), Type(..), joinForAlls, joinRows)
7import Docs.Search.TypeQuery (TypeQuery(..), getFreeVariables)
7import Docs.Search.TypeQuery (TypeQuery(..), getFreeVariables)
8+import Docs.Search.Types (Identifier(..))
8
9
9import Prelude
10import Prelude
10−
11+import Prim hiding (Type)
11import Data.Generic.Rep (class Generic)
12import Data.Generic.Rep (class Generic)
12−import Data.Generic.Rep.Show (genericShow)
13+import Data.Show.Generic (genericShow)
13import Data.List (List(..), (:))
14import Data.List (List(..), (:))
14import Data.List as List
15import Data.List as List
15import Data.List.NonEmpty as NonEmptyList
16import Data.List.NonEmpty as NonEmptyList
@@ -101,8 +102,8 @@ shapeOfType ty = List.reverse $ go (pure ty) Nil
101 TypeWildcard ->
102 TypeWildcard ->
102 go rest (PVar : acc)
103 go rest (PVar : acc)
103
104
104− TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Prim"]
105+ TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleNameParts: ["Prim"]
105− , name: "Function" })) t1) t2 ->
106+ , name: Identifier "Function" })) t1) t2 ->
106 go (t1 : t2 : rest) (PFun : acc)
107 go (t1 : t2 : rest) (PFun : acc)
107
108
108 TypeConstructor (QualifiedName { name }) ->
109 TypeConstructor (QualifiedName { name }) ->
@@ -114,6 +115,9 @@ shapeOfType ty = List.reverse $ go (pure ty) Nil
114 TypeApp child1 child2 ->
115 TypeApp child1 child2 ->
115 go (child1 : child2 : rest) (PApp : acc)
116 go (child1 : child2 : rest) (PApp : acc)
116
117
118+ KindApp child1 child2 ->
119+ go (child1 : child2 : rest) (PApp : acc)
120+
117 forallType@(ForAll _ _ _) ->
121 forallType@(ForAll _ _ _) ->
118 go (foralls.ty : rest) (PForAll (List.length foralls.binders) : acc)
122 go (foralls.ty : rest) (PForAll (List.length foralls.binders) : acc)
119 where foralls = joinForAlls forallType
123 where foralls = joinForAlls forallType
@@ -135,6 +139,8 @@ shapeOfType ty = List.reverse $ go (pure ty) Nil
135 sorted = List.sortBy (\x y -> compare x.row y.row) joined.rows
139 sorted = List.sortBy (\x y -> compare x.row y.row) joined.rows
136 typesInRow = sorted <#> (_.ty)
140 typesInRow = sorted <#> (_.ty)
137
141
142+ Kinded t1 _t2 -> go (t1 : rest) acc
143+
138 BinaryNoParensType op l r ->
144 BinaryNoParensType op l r ->
139 go (TypeApp (TypeApp op l) r : rest) acc
145 go (TypeApp (TypeApp op l) r : rest) acc
140
146
src/Docs/Search/Types.purs+101−2
@@ -1,5 +1,104 @@
1module Docs.Search.Types where
1module Docs.Search.Types where
2
2
3−type ModuleName = String
3+import Prelude
4
4
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.
5−type PackageName = String
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 @@
1/* global exports history */
1/* global exports history */
2
2
3// https://stackoverflow.com/questions/1397329
3// https://stackoverflow.com/questions/1397329
4−exports.removeHash = function () {
4+export function removeHash () {
5 var scrollV, scrollH, loc = window.location;
5 var scrollV, scrollH, loc = window.location;
6 if ("pushState" in history)
6 if ("pushState" in history)
7 history.pushState("", document.title, loc.pathname + loc.search);
7 history.pushState("", document.title, loc.pathname + loc.search);
src/Docs/Search/URIHash.purs+3−3
@@ -7,10 +7,10 @@ where
7
7
8import Prelude
8import Prelude
9
9
10−import Data.Maybe (Maybe(Just), fromMaybe)
10+import Data.Maybe (fromMaybe)
11import Data.String.CodeUnits as String
11import Data.String.CodeUnits as String
12import Effect (Effect)
12import Effect (Effect)
13−import Global (decodeURIComponent, encodeURIComponent)
13+import JSURI (decodeURIComponent, encodeURIComponent)
14import Web.HTML as HTML
14import Web.HTML as HTML
15import Web.HTML.Location as Location
15import Web.HTML.Location as Location
16import Web.HTML.Window as Window
16import Web.HTML.Window as Window
@@ -31,7 +31,7 @@ getInput = do
31 location <- Window.location window
31 location <- Window.location window
32 hash <- Location.hash location
32 hash <- Location.hash location
33 pure $
33 pure $
34− if String.slice 0 8 hash == Just "#search:"
34+ if String.slice 0 8 hash == "#search:"
35 then fromMaybe "" $
35 then fromMaybe "" $
36 decodeURIComponent $
36 decodeURIComponent $
37 String.drop 8 hash
37 String.drop 8 hash
test/Main.purs+14−558
@@ -2,572 +2,28 @@ module Test.Main where
2
2
3import Prelude
3import Prelude
4
4
5−import Docs.Search.TypeDecoder (Constraint(..), FunDep(..), FunDeps(..), Kind(..), QualifiedName(..), Type(..))
5+import Effect (Effect)
6−import Test.TypeQuery as TypeQuery
6+import Effect.Aff (launchAff_)
7−import Test.IndexBuilder as IndexBuilder
8import Test.Declarations as Declarations
7import Test.Declarations as Declarations
8+import Test.IndexBuilder as IndexBuilder
9import Test.ModuleIndex as ModuleIndex
9import Test.ModuleIndex as ModuleIndex
10−
10+import Test.ModuleParser as ModuleParser
11−import Test.Extra (assertRight)
11+import Test.Spec (Spec)
12−
12+import Test.Spec.Reporter.Console (consoleReporter)
13−import Data.Argonaut.Decode (decodeJson)
13+import Test.Spec.Runner (runSpec)
14−import Data.Argonaut.Encode (encodeJson)
14+import Test.TypeJson as TypeJson
15−import Data.Argonaut.Parser (jsonParser)
15+import Test.TypeQuery as TypeQuery
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)
22
16
23main :: Effect Unit
17main :: Effect Unit
24main = do
18main = do
25− runTest mainTest
19+ launchAff_ $ runSpec [consoleReporter] mainTest
20+ -- UI.main
26
21
27−mainTest :: TestSuite
22+mainTest :: Spec Unit
28mainTest = do
23mainTest = do
24+ ModuleParser.tests
29 TypeQuery.tests
25 TypeQuery.tests
26+ TypeJson.tests
30 IndexBuilder.tests
27 IndexBuilder.tests
31 Declarations.tests
28 Declarations.tests
32 ModuleIndex.tests
29 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
2
2
3import Prelude
3import Prelude
4
4
5−import Data.Maybe (Maybe(..))
6import Docs.Search.Declarations (extractPackageName)
5import Docs.Search.Declarations (extractPackageName)
6+import Docs.Search.Types (PackageName(..), PackageInfo(..))
7
7
8−import Test.Unit (TestSuite, suite, test)
8+import Data.Maybe (Maybe(..))
9−import Test.Unit.Assert as Assert
9+import Data.Newtype (wrap)
10+import Test.Spec (Spec, describe, it)
11+import Test.Spec.Assertions (shouldEqual)
10
12
11−tests :: TestSuite
13+tests :: Spec Unit
12tests = do
14tests = do
13− suite "Declarations" do
15+ describe "Declarations" do
14− test "extractPackageName" do
16+ it "extractPackageName works correctly" do
15− Assert.equal "<builtin>" (extractPackageName "Prim" Nothing)
17+ Builtin `shouldEqual` (extractPackageName (wrap "Prim") Nothing)
16− Assert.equal "<builtin>" (extractPackageName "Prim.Foo" Nothing)
18+ Builtin `shouldEqual` (extractPackageName (wrap "Prim.Foo") Nothing)
17− Assert.equal "<builtin>" (extractPackageName "Prim.Foo.Bar" Nothing)
19+ Builtin `shouldEqual` (extractPackageName (wrap "Prim.Foo.Bar") Nothing)
18− Assert.equal "<unknown>" (extractPackageName "Primitive" Nothing)
20+ UnknownPackage `shouldEqual` (extractPackageName (wrap "Primitive") Nothing)
19− Assert.equal "foo"
21+ Package (PackageName "foo") `shouldEqual`
20− (extractPackageName "Foo" $
22+ (extractPackageName (wrap "Foo") $
21 Just { start: []
23 Just { start: []
22 , end: []
24 , end: []
23 , name: ".spago/foo/src/Foo.purs"
25 , name: ".spago/foo/src/Foo.purs"
24 }
26 }
25 )
27 )
26− Assert.equal "bar"
28+ Package (PackageName "bar") `shouldEqual`
27− (extractPackageName "Bar" $
29+ (extractPackageName (wrap "Bar") $
28 Just { start: []
30 Just { start: []
29 , end: []
31 , end: []
30 , name: "/path/to/somewhere/bower_components/bar/src/Bar.purs"
32 , name: "/path/to/somewhere/bower_components/bar/src/Bar.purs"
31 }
33 }
32 )
34 )
33− Assert.equal "<local package>"
35+ LocalPackage `shouldEqual`
34− (extractPackageName "Bar" $
36+ (extractPackageName (wrap "Bar") $
35 Just { start: []
37 Just { start: []
36 , end: []
38 , end: []
37 , name: "/path/to/somewhere/src/Bar.purs"
39 , name: "/path/to/somewhere/src/Bar.purs"
test/Test/Extra.purs+6−5
@@ -4,7 +4,8 @@ import Prelude
4
4
5import Data.Either (Either(..))
5import Data.Either (Either(..))
6import Effect.Aff (Aff)
6import Effect.Aff (Aff)
7−import Test.Unit.Assert as Assert
7+import Test.Spec.Assertions (shouldEqual)
8+
8
9
9assertRight
10assertRight
10 :: forall a b
11 :: forall a b
@@ -17,7 +18,7 @@ assertRight
17 -> Aff Unit
18 -> Aff Unit
18assertRight eiActual expected =
19assertRight eiActual expected =
19 case eiActual of
20 case eiActual of
20− Left string -> do
21+ Left _ -> do
21− Assert.equal (Right expected) eiActual
22+ Right expected `shouldEqual` eiActual
22− Right actual -> do
23+ Right _ -> do
23− Assert.equal (Right expected) eiActual
24+ Right expected `shouldEqual` eiActual
test/Test/IndexBuilder.purs+9−9
@@ -5,16 +5,16 @@ import Prelude
5import Docs.Search.IndexBuilder (patchHTML)
5import Docs.Search.IndexBuilder (patchHTML)
6
6
7import Data.Tuple (snd)
7import Data.Tuple (snd)
8−import Test.Unit (TestSuite, suite, test)
8+import Test.Spec (Spec, describe, it)
9−import Test.Unit.Assert as Assert
9+import Test.Spec.Assertions (shouldEqual, shouldNotSatisfy)
10
10
11−tests :: TestSuite
11+tests :: Spec Unit
12tests = do
12tests = do
13− suite "IndexBuilder" do
13+ describe "IndexBuilder" do
14− suite "patchHTML" do
14+ describe "patchHTML" do
15− test "works" do
15+ it "works" do
16 let input = "</body>"
16 let input = "</body>"
17− Assert.assertFalse "patchHTML works" (snd (patchHTML input) == input)
17+ shouldNotSatisfy (snd (patchHTML input)) (eq input)
18− test "is idempotent" do
18+ it "is idempotent" do
19 let input = "</body>"
19 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)
5import Prelude
5import Prelude
6
6
7import Data.List as List
7import Data.List as List
8−import Test.Unit (TestSuite, suite, test)
8+import Data.Newtype (wrap)
9−import Test.Unit.Assert as Assert
9+import Test.Spec (Spec, describe, it)
10+import Test.Spec.Assertions (shouldEqual)
10
11
11
12
12−tests :: TestSuite
13+tests :: Spec Unit
13tests = do
14tests = do
14− suite "ModuleIndex" do
15+ describe "ModuleIndex" do
15
16
16− test "test #0" do
17+ it "test #0" do
17− Assert.equal (extractModuleNameParts "Data.Array.ST") (
18+ extractModuleNameParts (wrap "Data.Array.ST") `shouldEqual`
18 List.fromFoldable [ "st", "array.st", "data.array.st" ]
19 List.fromFoldable [ "st", "array.st", "data.array.st" ]
19− )
20
20
21− test "test #1" do
21+ it "test #1" do
22− Assert.equal (extractModuleNameParts "Foo") (
22+ extractModuleNameParts (wrap "Foo") `shouldEqual`
23 List.fromFoldable [ "foo" ]
23 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
3import Docs.Search.TypeDecoder (Constraint(..), QualifiedName(..), Type(..))
3import Docs.Search.TypeDecoder (Constraint(..), QualifiedName(..), Type(..))
4import Docs.Search.TypeQuery (Substitution(..), TypeQuery(..), getFreeVariables, parseTypeQuery, penalty, typeVarPenalty)
4import Docs.Search.TypeQuery (Substitution(..), TypeQuery(..), getFreeVariables, parseTypeQuery, penalty, typeVarPenalty)
5import Docs.Search.TypeShape (ShapeChunk(..), shapeOfType, shapeOfTypeQuery)
5import Docs.Search.TypeShape (ShapeChunk(..), shapeOfType, shapeOfTypeQuery)
6+import Docs.Search.Types (Identifier(..))
6
7
7import Prelude
8import Prelude
8−
9+import Prim hiding (Constraint, Type)
9import Data.Foldable (class Foldable)
10import Data.Foldable (class Foldable)
10import Data.List (List(..), (:))
11import Data.List (List(..), (:))
11import Data.List as List
12import Data.List as List
@@ -14,392 +15,566 @@ import Data.List.NonEmpty as NonEmptyList
14import Data.Set as Set
15import Data.Set as Set
15import Data.Tuple (Tuple(..))
16import Data.Tuple (Tuple(..))
16import Test.Extra (assertRight)
17import Test.Extra (assertRight)
17−import Test.Unit (TestSuite, suite, test)
18+import Test.Spec (Spec, describe, it)
18−import Test.Unit.Assert as Assert
19+import Test.Spec.Assertions (shouldEqual, shouldSatisfy)
19import Data.Maybe (Maybe(..))
20import Data.Maybe (Maybe(..))
20
21
21−
22+tests :: Spec Unit
22−tests :: TestSuite
23tests = do
23tests = do
24− suite "TypeQuery parser" do
24+ describe "TypeQuery parser" do
25
25
26− test "test #0" do
26+ it "test #0" do
27 let input = "a"
27 let input = "a"
28− assertRight (parseTypeQuery input) (QVar "a")
28+ assertRight (parseTypeQuery input) (qVar "a")
29
29
30− test "test #1" do
30+ it "test #1" do
31 let input = "ab"
31 let input = "ab"
32− assertRight (parseTypeQuery input) (QVar "ab")
32+ assertRight (parseTypeQuery input) (qVar "ab")
33
33
34− test "test #2" do
34+ it "test #2" do
35 let input = "a b"
35 let input = "a b"
36− assertRight (parseTypeQuery input) (QApp (QVar "a") (QVar "b"))
36+ assertRight (parseTypeQuery input) (QApp (qVar "a") (qVar "b"))
37
37
38− test "test #3" do
38+ it "test #3" do
39 let input = "a b c"
39 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"))
41
41
42− test "test #4" do
42+ it "test #4" do
43 let input = "a -> b"
43 let input = "a -> b"
44− assertRight (parseTypeQuery input) (QFun (QVar "a") (QVar "b"))
44+ assertRight (parseTypeQuery input) (QFun (qVar "a") (qVar "b"))
45
45
46− test "test #5" do
46+ it "test #5" do
47 let input = "a -> b c"
47 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")))
49
49
50− test "test #6" do
50+ it "test #6" do
51 let input = "a b -> c"
51 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"))
53
53
54− test "test #7" do
54+ it "test #7" do
55 let input = "a b"
55 let input = "a b"
56− assertRight (parseTypeQuery input) (QApp (QVar "a") (QVar "b"))
56+ assertRight (parseTypeQuery input) (QApp (qVar "a") (qVar "b"))
57
57
58− test "test #8" do
58+ it "test #8" do
59 let input = "a (b c)"
59 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")))
61
61
62− test "test #9" do
62+ it "test #9" do
63 let input = "(a b) (c d)"
63 let input = "(a b) (c d)"
64 assertRight (parseTypeQuery input)
64 assertRight (parseTypeQuery input)
65− (QApp (QApp (QVar "a") (QVar "b"))
65+ ( QApp (QApp (qVar "a") (qVar "b"))
66− (QApp (QVar "c") (QVar "d")))
66+ (QApp (qVar "c") (qVar "d"))
67+ )
67
68
68− test "test #10" do
69+ it "test #10" do
69 let input = "a ( b c )"
70 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")))
71
72
72− test "test #11" do
73+ it "test #11" do
73 let input = "aaa"
74 let input = "aaa"
74− assertRight (parseTypeQuery input) (QVar "aaa")
75+ assertRight (parseTypeQuery input) (qVar "aaa")
75
76
76− test "test #12" do
77+ it "test #12" do
77 let input = "aaa ( bbb ccc )"
78 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")))
79
80
80− test "test #13" do
81+ it "test #13" do
81 let input = "(a -> b) -> (c -> d)"
82 let input = "(a -> b) -> (c -> d)"
82− assertRight (parseTypeQuery input) (QFun (QFun (QVar "a") (QVar "b"))
83+ assertRight (parseTypeQuery input)
84+ ( QFun (QFun (qVar "a") (qVar "b"))
83− (QFun (QVar "c") (QVar "d")))
85+ (QFun (qVar "c") (qVar "d"))
86+ )
84
87
85− test "test #14" do
88+ it "test #14" do
86 let input = "a -> b -> c -> d"
89 let input = "a -> b -> c -> d"
87− assertRight (parseTypeQuery input) (QFun (QVar "a")
90+ assertRight (parseTypeQuery input)
91+ ( QFun (qVar "a")
88− (QFun (QVar "b")
92+ ( QFun (qVar "b")
89− (QFun (QVar "c") (QVar "d"))))
93+ (QFun (qVar "c") (qVar "d"))
94+ )
95+ )
90
96
91− test "test #15" do
97+ it "test #15" do
92 let input = "a -> b -> c"
98 let input = "a -> b -> c"
93− assertRight (parseTypeQuery input) (QFun (QVar "a")
99+ assertRight (parseTypeQuery input)
100+ ( QFun (qVar "a")
94− (QFun (QVar "b")
101+ ( QFun (qVar "b")
95− (QVar "c")))
102+ (qVar "c")
103+ )
104+ )
96
105
97− test "test #16" do
106+ it "test #16" do
98 let input = "forall a b c. c"
107 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"))
100
109
101− test "test #17" do
110+ it "test #17" do
102 let input = "forall a. Maybe a"
111 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")))
104
113
105− test "test #18" do
114+ it "test #18" do
106 let input = "forall m a. Monad m => a -> m a"
115 let input = "forall m a. Monad m => a -> m a"
107 assertRight (parseTypeQuery input)
116 assertRight (parseTypeQuery input)
108− (QForAll (nl "m" ["a"])
117+ ( QForAll (nl "m" [ "a" ])
109− (QConstraint "Monad" (l [QVar "m"])
118+ ( qConstraint "Monad" (l [ qVar "m" ])
110− (QFun (QVar "a")
119+ ( QFun (qVar "a")
111− (QApp (QVar "m") (QVar "a")))))
120+ (QApp (qVar "m") (qVar "a"))
112−
121+ )
122+ )
123+ )
124+
113− test "test #19" do
125+ it "test #19" do
114 let input = "{ a :: Int }"
126 let input = "{ a :: Int }"
115 assertRight (parseTypeQuery input)
127 assertRight (parseTypeQuery input)
116− (QApp (QConst "Record") (QRow (pure (Tuple "a" (QConst "Int")))))
128+ (QApp (qConst "Record") (QRow (pure (Tuple (Identifier "a") (qConst "Int")))))
117
129
118− test "test #20" do
130+ it "test #20" do
119 let input = "{a::Int}"
131 let input = "{a::Int}"
120 assertRight (parseTypeQuery input)
132 assertRight (parseTypeQuery input)
121− (QApp (QConst "Record") (QRow (pure (Tuple "a" (QConst "Int")))))
133+ (QApp (qConst "Record") (QRow (pure (Tuple (Identifier "a") (qConst "Int")))))
122
134
123− test "test #21" do
135+ it "test #21" do
124 let input = "Int"
136 let input = "Int"
125− assertRight (parseTypeQuery input) (QConst "Int")
137+ assertRight (parseTypeQuery input) (qConst "Int")
126
138
127− test "test #22" do
139+ it "test #22" do
128 let input = "a->b"
140 let input = "a->b"
129− assertRight (parseTypeQuery input) (QFun (QVar "a") (QVar "b"))
141+ assertRight (parseTypeQuery input) (QFun (qVar "a") (qVar "b"))
130
142
131− test "test #23" do
143+ it "test #23" do
132 let input = "forall m a. MonadRec m => Process m a -> m a"
144 let input = "forall m a. MonadRec m => Process m a -> m a"
133− assertRight (parseTypeQuery input) (QForAll (nl "m" ("a" : Nil))
145+ assertRight (parseTypeQuery input)
146+ ( QForAll (nl "m" ("a" : Nil))
134− (QConstraint "MonadRec" (l [QVar "m"])
147+ ( qConstraint "MonadRec" (l [ qVar "m" ])
148+ ( QFun
149+ ( QApp
135− (QFun (QApp (QApp (QConst "Process")
150+ ( QApp (qConst "Process")
136− (QVar "m")) (QVar "a"))
151+ (qVar "m")
152+ )
153+ (qVar "a")
154+ )
137− (QApp (QVar "m") (QVar "a")))))
155+ (QApp (qVar "m") (qVar "a"))
138−
156+ )
157+ )
158+ )
159+
139− test "test #24" do
160+ it "test #24" do
140 let input = "forall t f a. Foldable1 t => Apply f => f"
161 let input = "forall t f a. Foldable1 t => Apply f => f"
141− assertRight (parseTypeQuery input) (QForAll (nl "t" ["f", "a"])
162+ assertRight (parseTypeQuery input)
163+ ( QForAll (nl "t" [ "f", "a" ])
142− (QConstraint "Foldable1" (l [QVar "t"])
164+ ( qConstraint "Foldable1" (l [ qVar "t" ])
143− (QConstraint "Apply" (l [QVar "f"]) (QVar "f"))))
165+ (qConstraint "Apply" (l [ qVar "f" ]) (qVar "f"))
166+ )
167+ )
144
168
145− test "test #25" do
169+ it "test #25" do
146 let input = "forall m a.MonadRec m=>Process m a->m a"
170 let input = "forall m a.MonadRec m=>Process m a->m a"
147− assertRight (parseTypeQuery input) ((QForAll (nl "m" ("a" : Nil))
171+ assertRight (parseTypeQuery input)
172+ ( ( QForAll (nl "m" ("a" : Nil))
148− (QConstraint "MonadRec" (l [QVar "m"])
173+ ( qConstraint "MonadRec" (l [ qVar "m" ])
174+ ( QFun
175+ ( QApp
149− (QFun (QApp (QApp (QConst "Process")
176+ ( QApp (qConst "Process")
150− (QVar "m")) (QVar "a"))
177+ (qVar "m")
178+ )
179+ (qVar "a")
180+ )
151− (QApp (QVar "m") (QVar "a"))))))
181+ (QApp (qVar "m") (qVar "a"))
152−
182+ )
183+ )
184+ )
185+ )
186+
153− test "test #26" do
187+ it "test #26" do
154 let input = "m a -> (a -> m b) -> m b"
188 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"))))
156
190
157− test "test #27" do
191+ it "test #27" do
158 let input = "forall f a. Alternative f => Lazy (f (List a)) => f a -> f (List a)"
192 let input = "forall f a. Alternative f => Lazy (f (List a)) => f a -> f (List a)"
159− assertRight (parseTypeQuery input) ((QForAll (nl "f" ["a"]))
193+ assertRight (parseTypeQuery input)
194+ ( (QForAll (nl "f" [ "a" ]))
160− (QConstraint "Alternative" (l [QVar "f"])
195+ ( qConstraint "Alternative" (l [ qVar "f" ])
161− (QConstraint "Lazy" (l [QApp (QVar "f")
196+ ( qConstraint "Lazy"
197+ ( l
198+ [ QApp (qVar "f")
162− (QApp (QConst "List") (QVar "a"))])
199+ (QApp (qConst "List") (qVar "a"))
200+ ]
201+ )
163− (QFun (QApp (QVar "f") (QVar "a"))
202+ ( QFun (QApp (qVar "f") (qVar "a"))
164− (QApp (QVar "f")
203+ ( QApp (qVar "f")
165− (QApp (QConst "List") (QVar "a")))))))
204+ (QApp (qConst "List") (qVar "a"))
166−
205+ )
206+ )
207+ )
208+ )
209+ )
210+
167− test "test #28" do
211+ it "test #28" do
168 let input = "forall f a. Alternative f => Lazy(f (List a))=>f a -> f (List a)"
212 let input = "forall f a. Alternative f => Lazy(f (List a))=>f a -> f (List a)"
169− assertRight (parseTypeQuery input) ((QForAll (nl "f" ["a"]))
213+ assertRight (parseTypeQuery input)
214+ ( (QForAll (nl "f" [ "a" ]))
170− (QConstraint "Alternative" (l [QVar "f"])
215+ ( qConstraint "Alternative" (l [ qVar "f" ])
171− (QConstraint "Lazy" (l [QApp (QVar "f")
216+ ( qConstraint "Lazy"
217+ ( l
218+ [ QApp (qVar "f")
172− (QApp (QConst "List") (QVar "a"))])
219+ (QApp (qConst "List") (qVar "a"))
220+ ]
221+ )
173− (QFun (QApp (QVar "f") (QVar "a"))
222+ ( QFun (QApp (qVar "f") (qVar "a"))
174− (QApp (QVar "f")
223+ ( QApp (qVar "f")
175− (QApp (QConst "List") (QVar "a")))))))
224+ (QApp (qConst "List") (qVar "a"))
176−
225+ )
226+ )
227+ )
228+ )
229+ )
230+
177− test "test #29" do
231+ it "test #29" do
178 let input = "{a::Int,b::Int}"
232 let input = "{a::Int,b::Int}"
179 assertRight (parseTypeQuery input)
233 assertRight (parseTypeQuery input)
180− (QApp (QConst "Record") (QRow (List.fromFoldable [ Tuple "a" (QConst "Int"), Tuple "b" (QConst "Int")])))
234+ ( QApp (qConst "Record")
181−
235+ ( QRow
236+ ( List.fromFoldable
237+ [ Tuple (Identifier "a") (qConst "Int")
238+ , Tuple (Identifier "b") (qConst "Int")
239+ ]
240+ )
241+ )
242+ )
243+
182− test "test #30" do
244+ it "test #30" do
183 let input = "{record''' :: Int}"
245 let input = "{record''' :: Int}"
184 assertRight (parseTypeQuery input)
246 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") ])))
186
248
187− test "test #31" do
249+ it "test #31" do
188 let input = "(row''' :: Int)"
250 let input = "(row''' :: Int)"
189 assertRight (parseTypeQuery input)
251 assertRight (parseTypeQuery input)
190− (QRow (List.fromFoldable [ Tuple "row'''" (QConst "Int")]))
252+ (QRow (List.fromFoldable [ Tuple (Identifier "row'''") (qConst "Int") ]))
191
253
192− test "test #32" do
254+ it "test #32" do
193 let input = "(row1 :: Int, row2 :: (),row3::(row4::{}))"
255 let input = "(row1 :: Int, row2 :: (),row3::(row4::{}))"
194 assertRight (parseTypeQuery input)
256 assertRight (parseTypeQuery input)
257+ ( QRow
258+ ( l
195− (QRow (l [ Tuple "row1" (QConst "Int")
259+ [ Tuple (Identifier "row1") (qConst "Int")
196− , Tuple "row2" (QRow Nil)
260+ , Tuple (Identifier "row2") (QRow Nil)
197− , Tuple "row3" (QRow (l [ Tuple "row4" (QApp (QConst "Record") (QRow Nil)) ])) ]))
261+ , Tuple (Identifier "row3") (QRow (l [ Tuple (Identifier "row4") (QApp (qConst "Record") (QRow Nil)) ]))
198−
262+ ]
263+ )
264+ )
265+
199− test "test #33" do
266+ it "test #33" do
200 let input = "Foldable1 t => Apply f => t (f a) -> f Unit"
267 let input = "Foldable1 t => Apply f => t (f a) -> f Unit"
201 assertRight (parseTypeQuery input)
268 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")))))
203
270
204− test "test #34" do
271+ it "test #34" do
205 let input = "Foldable1 t => Apply f => t (f a) -> f a"
272 let input = "Foldable1 t => Apply f => t (f a) -> f a"
206 assertRight (parseTypeQuery input)
273 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")))))
208
275
209− test "test #35" do
276+ it "test #35" do
210 let input = "Generic a rep => GenericEq rep => a -> a -> Boolean"
277 let input = "Generic a rep => GenericEq rep => a -> a -> Boolean"
211 assertRight (parseTypeQuery input)
278 assertRight (parseTypeQuery input)
212− (QConstraint "Generic" ((QVar "a") : (QVar "rep") : Nil)
279+ ( qConstraint "Generic" ((qVar "a") : (qVar "rep") : Nil)
213− (QConstraint "GenericEq" ((QVar "rep") : Nil)
280+ ( qConstraint "GenericEq" ((qVar "rep") : Nil)
214− (QFun (QVar "a") (QFun (QVar "a") (QConst "Boolean")))))
281+ (QFun (qVar "a") (QFun (qVar "a") (qConst "Boolean")))
282+ )
283+ )
215
284
216− suite "polish notation" do
285+ describe "polish notation" do
217
286
218− test "test #1" do
287+ it "test #1" do
219 let input = "(a -> b) -> (b -> ((a -> b) -> c))"
288 let input = "(a -> b) -> (b -> ((a -> b) -> c))"
220 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
289 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
221− (l [ PForAll 3, PFun, PFun, PVar, PVar, PFun, PVar, PFun, PFun
290+ ( l
291+ [ PForAll 3
292+ , PFun
293+ , PFun
294+ , PVar
295+ , PVar
296+ , PFun
297+ , PVar
298+ , PFun
299+ , PFun
222− , PVar, PVar, PVar ])
300+ , PVar
223−
301+ , PVar
302+ , PVar
303+ ]
304+ )
305+
224− test "test #2" do
306+ it "test #2" do
225 let input = "forall a. (a -> b) -> (b -> ((a -> b) -> c))"
307 let input = "forall a. (a -> b) -> (b -> ((a -> b) -> c))"
226 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
308 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
227− (l [ PForAll 3, PFun, PFun, PVar, PVar, PFun, PVar, PFun, PFun
309+ ( l
310+ [ PForAll 3
311+ , PFun
312+ , PFun
313+ , PVar
314+ , PVar
315+ , PFun
316+ , PVar
317+ , PFun
318+ , PFun
228− , PVar, PVar, PVar ])
319+ , PVar
229−
320+ , PVar
321+ , PVar
322+ ]
323+ )
324+
230− test "test #3" do
325+ it "test #3" do
231 let input = "forall a. (a -> b) -> (b -> ((a -> b) -> c))"
326 let input = "forall a. (a -> b) -> (b -> ((a -> b) -> c))"
232 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
327 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
233− (l [ PForAll 3, PFun, PFun, PVar, PVar, PFun, PVar, PFun, PFun
328+ ( l
329+ [ PForAll 3
330+ , PFun
331+ , PFun
332+ , PVar
333+ , PVar
334+ , PFun
335+ , PVar
336+ , PFun
337+ , PFun
234− , PVar, PVar, PVar ])
338+ , PVar
235−
339+ , PVar
340+ , PVar
341+ ]
342+ )
343+
236− test "test #4" do
344+ it "test #4" do
237 let input = "forall a. (forall h. ST h (STArray h a)) -> Array a"
345 let input = "forall a. (forall h. ST h (STArray h a)) -> Array a"
238 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
346 assertRight (shapeOfTypeQuery <$> parseTypeQuery input)
239− (l [ PForAll 1, PFun, PForAll 1, PApp, PApp, PVar, PVar, PApp, PApp, PVar, PVar, PVar, PApp, PVar, PVar ])
347+ (l [ PForAll 1, PFun, PForAll 1, PApp, PApp, PVar, PVar, PApp, PApp, PVar, PVar, PVar, PApp, PVar, PVar ])
240−
348+
241− suite "type shapes" do
349+ describe "type shapes" do
242− test "test #1" do
350+ it "test #1" do
351+ let
243− let query = "Generic a rep => GenericEq rep => a -> a -> Boolean"
352+ query = "Generic a rep => GenericEq rep => a -> a -> Boolean"
244− c1 = constr (qname [""] "Generic") [TypeVar "a", TypeVar "rep"]
353+ c1 = constr (qname [ "" ] "Generic") [ TypeVar "a", TypeVar "rep" ]
245− c2 = constr (qname [""] "GenericEq") [TypeVar "rep"]
354+ c2 = constr (qname [ "" ] "GenericEq") [ TypeVar "rep" ]
246−
355+
247− fun t1 t2 =
356+ fun t1 t2 =
357+ TypeApp
358+ ( TypeApp
248− TypeApp (TypeApp (TypeConstructor (QualifiedName { moduleName: ["Prim"]
359+ ( TypeConstructor
360+ ( QualifiedName
361+ { moduleNameParts: [ "Prim" ]
249− , name: "Function" })) t1) t2
362+ , name: Identifier "Function"
363+ }
364+ )
365+ )
366+ t1
367+ )
368+ t2
250− type_ =
369+ type_ =
251− ForAll "a" Nothing $
370+ ForAll "a" Nothing
252− ForAll "rep" Nothing $
371+ $ ForAll "rep" Nothing
372+ $
253− ConstrainedType c1
373+ ConstrainedType c1
254− (ConstrainedType c2
374+ ( ConstrainedType c2
255− (fun (TypeVar "a") (fun (TypeVar "b")
375+ ( fun (TypeVar "a")
376+ ( fun (TypeVar "b")
256− (TypeConstructor $ qname ["Prim", "Boolean"] "Boolean"))))
377+ (TypeConstructor $ qname [ "Prim", "Boolean" ] "Boolean")
378+ )
379+ )
380+ )
257− shape = shapeOfTypeQuery <$> parseTypeQuery query
381+ shape = shapeOfTypeQuery <$> parseTypeQuery query
258− Assert.equal (pure $ shapeOfType type_) shape
382+ pure (shapeOfType type_) `shouldEqual` shape
259−
383+
260− suite "free variable counting" do
384+ describe "free variable counting" do
261−
385+
262− test "test #1" do
386+ it "test #1" do
263 let input = "forall a. (a -> b) -> (b -> ((a -> b) -> c))"
387 let input = "forall a. (a -> b) -> (b -> ((a -> b) -> c))"
264 assertRight (countFreeVars <$> parseTypeQuery input) 2
388 assertRight (countFreeVars <$> parseTypeQuery input) 2
265
389
266− test "test #2" do
390+ it "test #2" do
267 -- `b` is not bound on the left, `a` is not bound on the right
391 -- `b` is not bound on the left, `a` is not bound on the right
268 let input = "(forall a. (a -> b)) -> forall b. (b -> a)"
392 let input = "(forall a. (a -> b)) -> forall b. (b -> a)"
269 assertRight (countFreeVars <$> parseTypeQuery input) 2
393 assertRight (countFreeVars <$> parseTypeQuery input) 2
270
394
271− test "test #3" do
395+ it "test #3" do
272 let input = "a -> forall a. a"
396 let input = "a -> forall a. a"
273 assertRight (countFreeVars <$> parseTypeQuery input) 1
397 assertRight (countFreeVars <$> parseTypeQuery input) 1
274
398
275− test "test #4" do
399+ it "test #4" do
276 let input = "(forall a. a) -> a"
400 let input = "(forall a. a) -> a"
277 assertRight (countFreeVars <$> parseTypeQuery input) 1
401 assertRight (countFreeVars <$> parseTypeQuery input) 1
278
402
279− test "test #5" do
403+ it "test #5" do
280 let input = "forall a. a -> a"
404 let input = "forall a. a -> a"
281 assertRight (countFreeVars <$> parseTypeQuery input) 0
405 assertRight (countFreeVars <$> parseTypeQuery input) 0
282
406
283− test "test #6" do
407+ it "test #6" do
284 let input = "a -> b -> c"
408 let input = "a -> b -> c"
285 assertRight (countFreeVars <$> parseTypeQuery input) 3
409 assertRight (countFreeVars <$> parseTypeQuery input) 3
286
410
287− test "test #7" do
411+ it "test #7" do
288 let input = "forall m a. Monad m => a -> m a"
412 let input = "forall m a. Monad m => a -> m a"
289 assertRight (countFreeVars <$> parseTypeQuery input) 0
413 assertRight (countFreeVars <$> parseTypeQuery input) 0
290
414
291− test "test #8" do
415+ it "test #8" do
292 let input = "Monad m => a -> m a"
416 let input = "Monad m => a -> m a"
293 assertRight (countFreeVars <$> parseTypeQuery input) 2
417 assertRight (countFreeVars <$> parseTypeQuery input) 2
294
418
295− test "test #9" do
419+ it "test #9" do
296 let input = "Monad m => a -> a"
420 let input = "Monad m => a -> a"
297 assertRight (countFreeVars <$> parseTypeQuery input) 2
421 assertRight (countFreeVars <$> parseTypeQuery input) 2
298
422
299− test "test #10" do
423+ it "test #10" do
300 let input = "forall a. (forall a. a) a"
424 let input = "forall a. (forall a. a) a"
301 assertRight (countFreeVars <$> parseTypeQuery input) 0
425 assertRight (countFreeVars <$> parseTypeQuery input) 0
302
426
303− test "test #11" do
427+ it "test #11" do
304 let input = "forall a. (forall b. a) a"
428 let input = "forall a. (forall b. a) a"
305 assertRight (countFreeVars <$> parseTypeQuery input) 0
429 assertRight (countFreeVars <$> parseTypeQuery input) 0
306
430
307− test "test #12" do
431+ it "test #12" do
308 let input = "forall a. (forall b. a) a b"
432 let input = "forall a. (forall b. a) a b"
309 assertRight (countFreeVars <$> parseTypeQuery input) 1
433 assertRight (countFreeVars <$> parseTypeQuery input) 1
310
434
311− suite "typeVarPenalty" do
435+ describe "typeVarPenalty" do
312−
436+
313− test "#0" do
437+ it "#0" do
314− Assert.equal 0 (typeVarPenalty mempty)
438+ 0 `shouldEqual` (typeVarPenalty mempty)
315−
439+
316− test "#1" do
440+ it "#1" do
441+ 0 `shouldEqual`
317− Assert.equal 0 (typeVarPenalty $ l [ Substitute "a" "b"
442+ ( typeVarPenalty $ l
318− , Substitute "b" "a"
443+ [ substitute "a" "b"
444+ , substitute "b" "a"
319− ])
445+ ]
320−
446+ )
447+
321− test "#2" do
448+ it "#2" do
449+ 0 `shouldEqual`
322− Assert.equal 0 (typeVarPenalty $ l [ Substitute "a" "b"
450+ ( typeVarPenalty $ l
323− , Substitute "a" "b"
451+ [ substitute "a" "b"
324− , Substitute "a" "b"
452+ , substitute "a" "b"
453+ , substitute "a" "b"
325− ])
454+ ]
326−
455+ )
456+
327− test "#3" do
457+ it "#3" do
458+ 1 `shouldEqual`
328− Assert.equal 1 (typeVarPenalty $ l [ Substitute "a" "b"
459+ ( typeVarPenalty $ l
329− , Substitute "a" "c"
460+ [ substitute "a" "b"
461+ , substitute "a" "c"
330− ])
462+ ]
331−
463+ )
464+
332− test "#4" do
465+ it "#4" do
466+ 1 `shouldEqual`
333− Assert.equal 1 (typeVarPenalty $ l [ Substitute "a" "b"
467+ ( typeVarPenalty $ l
334− , Substitute "b" "a"
468+ [ substitute "a" "b"
335− , Substitute "b" "c"
469+ , substitute "b" "a"
470+ , substitute "b" "c"
336− ])
471+ ]
337−
472+ )
473+
338− test "#5" do
474+ it "#5" do
475+ 0 `shouldEqual`
339− Assert.equal 0 (typeVarPenalty $ l [ Substitute "a" "b"
476+ ( typeVarPenalty $ l
340− , Substitute "b" "c"
477+ [ substitute "a" "b"
341− , Substitute "c" "a"
478+ , substitute "b" "c"
479+ , substitute "c" "a"
342− ])
480+ ]
343−
481+ )
482+
344− test "#6" do
483+ it "#6" do
484+ 2 `shouldEqual`
345− Assert.equal 2 (typeVarPenalty $ l [ Substitute "a" "b"
485+ ( typeVarPenalty $ l
346− , Substitute "a" "c"
486+ [ substitute "a" "b"
347− , Substitute "a" "a"
487+ , substitute "a" "c"
488+ , substitute "a" "a"
348− ])
489+ ]
349−
490+ )
491+
350− test "#7" do
492+ it "#7" do
493+ 2 `shouldEqual`
351− Assert.equal 2 (typeVarPenalty $ l [ Substitute "a" "a"
494+ ( typeVarPenalty $ l
352− , Substitute "b" "a"
495+ [ substitute "a" "a"
353− , Substitute "c" "a"
496+ , substitute "b" "a"
497+ , substitute "c" "a"
354− ])
498+ ]
355−
499+ )
500+
356− test "#8" do
501+ it "#8" do
502+ 4 `shouldEqual`
357− Assert.equal 4 (typeVarPenalty $ l [ Substitute "a" "a"
503+ ( typeVarPenalty $ l
358− , Substitute "b" "a"
504+ [ substitute "a" "a"
359− , Substitute "c" "a"
505+ , substitute "b" "a"
360− , Substitute "a" "b"
506+ , substitute "c" "a"
361− , Substitute "a" "c"
507+ , substitute "a" "b"
362− , Substitute "a" "a"
508+ , substitute "a" "c"
509+ , substitute "a" "a"
363− ])
510+ ]
364−
511+ )
512+
365− test "#9" do
513+ it "#9" do
514+ 0 `shouldEqual`
366− Assert.equal 0 (typeVarPenalty $ l [ Substitute "a" "e"
515+ ( typeVarPenalty $ l
367− , Substitute "b" "d"
516+ [ substitute "a" "e"
368− , Substitute "c" "f"
517+ , substitute "b" "d"
518+ , substitute "c" "f"
369− ])
519+ ]
370−
520+ )
521+
371− suite "unification" do
522+ describe "unification" do
372− test "instantiation #0" do
523+ it "instantiation #0" do
524+ let
373− let mVarQuery = QVar "m"
525+ mVarQuery = qVar "m"
374− unitConstQuery = QConst "Unit"
526+ unitConstQuery = qConst "Unit"
375−
527+
376− Assert.assert "instantiation #0" $
528+ shouldSatisfy
377− (penalty unitConstQuery unitType < penalty mVarQuery unitType)
529+ (penalty unitConstQuery unitType)
378−
530+ (_ < penalty mVarQuery unitType)
531+
379− test "generalization #0" do
532+ it "generalization #0" do
533+ let
380− let query = QVar "m"
534+ query = qVar "m"
381− t1 = TypeVar "m"
535+ t1 = TypeVar "m"
382−
536+
383− Assert.assert "qeneralization #0" $
537+ shouldSatisfy
384− (penalty query unitType > penalty query t1)
538+ (penalty query unitType)
385−
539+ (_ > penalty query t1)
386
540
387l :: forall f. Foldable f => (forall a. f a -> List a)
541l :: forall f. Foldable f => (forall a. f a -> List a)
388l = List.fromFoldable
542l = List.fromFoldable
389
543
390−nl :: forall t5 t6. Foldable t6 => t5 -> t6 t5 -> NonEmptyList t5
544+nl
545+ :: forall t
546+ . Foldable t
547+ => Functor t
548+ => String
549+ -> t String
550+ -> NonEmptyList Identifier
391−nl x rst = NonEmptyList.cons' x $ List.fromFoldable rst
551+nl x rst = NonEmptyList.cons' (Identifier x) $ List.fromFoldable (rst <#> Identifier)
392
552
393unitType :: Type
553unitType :: Type
394−unitType = TypeConstructor (QualifiedName { moduleName: []
554+unitType = TypeConstructor
555+ ( QualifiedName
556+ { moduleNameParts: []
395− , name: "Unit"
557+ , name: Identifier "Unit"
396− })
558+ }
559+ )
397
560
398countFreeVars :: TypeQuery -> Int
561countFreeVars :: TypeQuery -> Int
399countFreeVars = getFreeVariables >>> Set.size
562countFreeVars = getFreeVariables >>> Set.size
400
563
401qname :: Array String -> String -> QualifiedName
564qname :: Array String -> String -> QualifiedName
402−qname m n = QualifiedName { moduleName: m, name: n }
565+qname m n = QualifiedName { moduleNameParts: m, name: Identifier n }
403
566
404constr :: QualifiedName -> Array Type -> Constraint
567constr :: QualifiedName -> Array Type -> Constraint
405constr c a = Constraint { constraintClass: c, constraintArgs: a }
568constr 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