mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-11 19:17:09 +03:00
Merge branch 'sqlite3' into backports-electron-19-changes-to-12
This commit is contained in:
commit
8174b679e0
@ -4,7 +4,11 @@ module.exports = {
|
||||
commonjs: true,
|
||||
es2021: true,
|
||||
},
|
||||
extends: ["eslint:recommended", "plugin:node/recommended"],
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:node/recommended",
|
||||
"plugin:jsdoc/recommended"
|
||||
],
|
||||
overrides: [],
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest"
|
||||
@ -17,6 +21,9 @@ module.exports = {
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
"jsdoc"
|
||||
],
|
||||
globals: {
|
||||
atom: "writeable"
|
||||
}
|
||||
|
42
.github/workflows/documentation.yml
vendored
Normal file
42
.github/workflows/documentation.yml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
name: Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
jobs:
|
||||
documentation:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x]
|
||||
|
||||
steps:
|
||||
- name: Checkout the Latest Code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup NodeJS - ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Install Dependencies
|
||||
run: yarn install
|
||||
|
||||
- name: Generate Public JSDocs
|
||||
run: yarn run js-docs
|
||||
|
||||
- name: Generate Private JSDocs
|
||||
run: yarn run private-js-docs
|
||||
|
||||
- name: Commit All Changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: GH Action Documentation
|
7
.github/workflows/editor-tests.yml
vendored
7
.github/workflows/editor-tests.yml
vendored
@ -1,9 +1,9 @@
|
||||
name: Editor tests
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ATOM_JASMINE_REPORTER: list
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
@ -13,7 +13,8 @@ jobs:
|
||||
!startsWith(github.event.pull_request.title, '[skip-editor-ci]')
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-2019]
|
||||
# os: [ubuntu-20.04, macos-latest, windows-2019]
|
||||
os: [ubuntu-20.04, macos-latest]
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
@ -34,4 +35,4 @@ jobs:
|
||||
- name: Run tests
|
||||
uses: GabrielBB/xvfb-action@v1
|
||||
with:
|
||||
run: yarn start --test spec
|
||||
run: node script/run-tests.js spec
|
||||
|
168
.github/workflows/package-tests-linux.yml
vendored
168
.github/workflows/package-tests-linux.yml
vendored
@ -1,9 +1,9 @@
|
||||
name: Package tests for Pulsar on Linux
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
env:
|
||||
APM_PATH: ./apm/node_modules/atom-package-manager/bin/apm
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ATOM_JASMINE_REPORTER: list
|
||||
jobs:
|
||||
setup:
|
||||
name: Build Editor
|
||||
@ -12,12 +12,6 @@ jobs:
|
||||
!startsWith(github.event.pull_request.title, '[skip-package-ci]')
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Install windows-build-tools
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
run: |
|
||||
npm i --global windows-build-tools@4.0.0
|
||||
npm config set msvs_version 2019
|
||||
|
||||
- name: Checkout the latest code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@ -35,60 +29,144 @@ jobs:
|
||||
- name: build dependencies
|
||||
run: yarn build:apm
|
||||
|
||||
- name: Cache node_modules
|
||||
id: cache-node
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: linux-modules-${{ hashFiles('package.json') }}
|
||||
- name: build the editor
|
||||
run: (yarn dist deb || yarn dist deb) && mv binaries/*deb pulsar.deb
|
||||
|
||||
- name: Cache apm
|
||||
id: cache-apm
|
||||
- name: Cache pulsar
|
||||
id: cache-pulsar
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: apm
|
||||
key: linux-apm-${{ hashFiles('apm/package.json') }}
|
||||
path: pulsar.deb
|
||||
key: pulsar-${{ github.sha }}
|
||||
|
||||
test:
|
||||
name: Test Packages
|
||||
name: Package
|
||||
needs: setup
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 8
|
||||
matrix:
|
||||
include:
|
||||
- filter: autocomplete|language
|
||||
descr: syntax-related
|
||||
- filter: dark|light
|
||||
descr: themes
|
||||
- filter: git-diff|go-to-line|grammar-selector|line-ending-selector|autoflow|autosave|symbols-view|spell-check|bracket-matcher|whitespace|wrap-guide|snippets|encoding-selector
|
||||
descr: editor related
|
||||
- filter: deprecation-cop|dev-live-reload|incompatible-packages|package-generator|exception-reporting|metrics|update-package-dependencies|styleguide
|
||||
descr: development helpers
|
||||
- filter: welcome|about|background-tips|tabs|tree-view|archive-view|markdown-preview|status-bar|settings-view|notifications
|
||||
descr: UI elements
|
||||
- filter: image-view|bookmarks|keybinding-resolver|link|timecop
|
||||
descr: others
|
||||
- package: "atom-dark-syntax"
|
||||
- package: "atom-dark-ui"
|
||||
- package: "atom-light-syntax"
|
||||
- package: "atom-light-ui"
|
||||
- package: "base16-tomorrow-dark-theme"
|
||||
- package: "base16-tomorrow-light-theme"
|
||||
- package: "one-dark-ui"
|
||||
- package: "one-light-ui"
|
||||
- package: "one-dark-syntax"
|
||||
- package: "one-light-syntax"
|
||||
- package: "solarized-dark-syntax"
|
||||
- package: "solarized-light-syntax"
|
||||
- package: "about"
|
||||
- package: "archive-view"
|
||||
- package: "autocomplete-atom-api"
|
||||
- package: "autocomplete-css"
|
||||
- package: "autocomplete-html"
|
||||
- package: "autocomplete-plus"
|
||||
- package: "autocomplete-snippets"
|
||||
- package: "autoflow"
|
||||
- package: "autosave"
|
||||
- package: "background-tips"
|
||||
- package: "bookmarks"
|
||||
- package: "bracket-matcher"
|
||||
- package: "command-palette"
|
||||
- package: "dalek"
|
||||
- package: "deprecation-cop"
|
||||
- package: "dev-live-reload"
|
||||
- package: "encoding-selector"
|
||||
- package: "exception-reporting"
|
||||
- package: "find-and-replace"
|
||||
- package: "fuzzy-finder"
|
||||
- package: "github"
|
||||
- package: "git-diff"
|
||||
- package: "go-to-line"
|
||||
- package: "grammar-selector"
|
||||
- package: "image-view"
|
||||
- package: "incompatible-packages"
|
||||
- package: "keybinding-resolver"
|
||||
- package: "line-ending-selector"
|
||||
- package: "link"
|
||||
- package: "markdown-preview"
|
||||
- package: "notifications"
|
||||
- package: "open-on-github"
|
||||
- package: "package-generator"
|
||||
- package: "settings-view"
|
||||
- package: "snippets"
|
||||
- package: "spell-check"
|
||||
- package: "status-bar"
|
||||
- package: "styleguide"
|
||||
- package: "symbols-view"
|
||||
- package: "tabs"
|
||||
- package: "timecop"
|
||||
- package: "tree-view"
|
||||
- package: "update-package-dependencies"
|
||||
- package: "welcome"
|
||||
- package: "whitespace"
|
||||
- package: "wrap-guide"
|
||||
- package: "language-c"
|
||||
- package: "language-clojure"
|
||||
- package: "language-coffee-script"
|
||||
- package: "language-csharp"
|
||||
- package: "language-css"
|
||||
- package: "language-gfm"
|
||||
- package: "language-git"
|
||||
- package: "language-go"
|
||||
- package: "language-html"
|
||||
- package: "language-hyperlink"
|
||||
- package: "language-java"
|
||||
- package: "language-javascript"
|
||||
- package: "language-json"
|
||||
- package: "language-less"
|
||||
- package: "language-make"
|
||||
- package: "language-mustache"
|
||||
- package: "language-objective-c"
|
||||
- package: "language-perl"
|
||||
- package: "language-php"
|
||||
- package: "language-property-list"
|
||||
- package: "language-python"
|
||||
- package: "language-ruby"
|
||||
- package: "language-ruby-on-rails"
|
||||
- package: "language-rust-bundled"
|
||||
- package: "language-sass"
|
||||
- package: "language-shellscript"
|
||||
- package: "language-source"
|
||||
- package: "language-sql"
|
||||
- package: "language-text"
|
||||
- package: "language-todo"
|
||||
- package: "language-toml"
|
||||
- package: "language-typescript"
|
||||
- package: "language-xml"
|
||||
- package: "language-yaml"
|
||||
|
||||
steps:
|
||||
- name: Checkout the latest code
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup NodeJS
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Install Dependencies
|
||||
run: yarn install || yarn install
|
||||
|
||||
- name: Restore node_modules from Cache
|
||||
id: restore-node
|
||||
- name: Build Dependencies
|
||||
run: yarn build || yarn build
|
||||
|
||||
- name: Restore pulsar from Cache
|
||||
id: restore-pulsar
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: linux-modules-${{ hashFiles('package.json') }}
|
||||
path: pulsar.deb
|
||||
key: pulsar-${{ github.sha }}
|
||||
|
||||
- name: Restore apm from Cache
|
||||
id: restore-apm
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: apm
|
||||
key: linux-apm-${{ hashFiles('apm/package.json') }}
|
||||
- name: Install Pulsar
|
||||
run: sudo dpkg -i pulsar.deb && sudo apt-get -f install -y
|
||||
|
||||
- name: Run Package Tests for ${{ matrix.descr }}
|
||||
uses: GabrielBB/xvfb-action@v1
|
||||
with:
|
||||
run: node -e "require('./script/run-package-tests')(/${{ matrix.filter }}/)"
|
||||
- name: Install xvfb
|
||||
run: sudo apt-get install -y xvfb
|
||||
|
||||
- name: Run ${{ matrix.package }} Tests
|
||||
run: Xvfb :1 & cd node_modules/${{ matrix.package }} && if test -d spec; then DISPLAY=:1 pulsar --test spec; fi
|
||||
# run: node -e "require('./script/run-package-tests')(/${{ matrix.package }}/)"
|
||||
|
306
CHANGELOG.md
306
CHANGELOG.md
@ -1,14 +1,304 @@
|
||||
# Pulsar next version
|
||||
# Changelog
|
||||
|
||||
- Format inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
- Format defined in [Pulsar Change Log](PENDING_APPROVAL)
|
||||
- Project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## 1.102.0
|
||||
|
||||
- Fixed a bug where `pulsar` on Windows could never trigger
|
||||
- Fixed `github` package shelling out to `git` on macOS
|
||||
- Fixed minor bugs found during fixes to tests
|
||||
- Improved our testing infastructure to aide in finding and fixing further bugs
|
||||
- Updated many dependencies of Pulsar and its core packages
|
||||
- New Pulsar Icon on macOS
|
||||
- Selected text is styled by default
|
||||
- Restored `right-clicked` CSS class on tags
|
||||
- Fixed syntax highlighting on C++
|
||||
- Updated JavaScript snippets to modern ES6 syntax
|
||||
- PPM no longer assumes `master` for git branches
|
||||
|
||||
### Pulsar
|
||||
- Added: implement signing and notarizing for macOS, PR #4 lol [@Meadowsys](https://github.com/pulsar-edit/pulsar/pull/387)
|
||||
- Fixed: Pin `python` brew installation to `3.10` during MacOS Intel Cirrus Build [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/384)
|
||||
- Update: Bump `ppm` to `a46537c0b7f0eaaef5404ef88003951fdc988c65` [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/383)
|
||||
- Added: Add new macOS icon [@mdibella-dev](https://github.com/pulsar-edit/pulsar/pull/372)
|
||||
- Fixed: type $ as # [@Meadowsys](https://github.com/pulsar-edit/pulsar/pull/378)
|
||||
- Update: deps: Update github to v0.36.14-pretranspiled-take-2 [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/375)
|
||||
- Added: add style to selected text by default [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/238)
|
||||
- Added: Set Max Concurrent Package Tests [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/376)
|
||||
- Fixed: c++ fixes [@icecream17](https://github.com/pulsar-edit/pulsar/pull/369)
|
||||
- Update: deps: Update github to v0.36.14-pretranspiled [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/373)
|
||||
- Update `coffeescript` [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/361)
|
||||
- Updated: Misc Dependency Updates [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/362)
|
||||
- Added: Bundle `autocomplete-plus` [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/358)
|
||||
- Fixed: Add LICENSE.md to extra resources (resourcesPath) [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/354)
|
||||
- Fixed: Get Windows `pulsar` Working [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/340)
|
||||
- Fixed: Restore `right-clicked` class on a right-clicked tab [@savetheclocktower](https://github.com/pulsar-edit/pulsar/pull/368)
|
||||
- Updated: ppm: Update submodule to commit 4645ba2905747897b0 [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/371)
|
||||
- Added: Machine decaf tabs spec [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/367)
|
||||
- Added: Manually Decaf `tabs` package Specs [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/357)
|
||||
- Fixed: Uncomment and fix a settings-view package test [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/366)
|
||||
- Added: Decaf Changes from Manual and Machine Decaf to Main [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/356)
|
||||
- Added: Manual decafe tabs [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/352)
|
||||
- Added: Organize failing tests [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/307)
|
||||
- Fixed: autocomplete-snippets: Fix repo URL [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/341)
|
||||
- Updated: update apm message to pulsar -p [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/337)
|
||||
- Fixed: Replace incorrect spellings of 'macOS' with the correct one [@mdibella-dev](https://github.com/pulsar-edit/pulsar/pull/336)
|
||||
- Changed: use `let` and `const` in js snippets [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/326)
|
||||
- Fixed: Fix URI to correct address [@mdibella-dev](https://github.com/pulsar-edit/pulsar/pull/335)
|
||||
- Updated: update copyright year (2023) [@icecream17](https://github.com/pulsar-edit/pulsar/pull/332)
|
||||
|
||||
### ppm
|
||||
- Fixed: fix: Don't assume `master` when checking git packages for upgrades [@savetheclocktower](https://github.com/pulsar-edit/ppm/pull/56)
|
||||
- Fixed: meta: Normalize package.json and lockfile line endings [@DeeDeeG](https://github.com/pulsar-edit/ppm/pull/54)
|
||||
- Update: spec: Fixtures Node v10.20.1 --> Electron v12.2.3 [@DeeDeeG](https://github.com/pulsar-edit/ppm/pull/52)
|
||||
- Fixed: Fix .com links, pulsar rebranding and rebranding readme [@Daeraxa](https://github.com/pulsar-edit/ppm/pull/48)
|
||||
|
||||
### github
|
||||
- Fixed: lib: Rebrand getAtomAppName() function (fix shelling out to `git` on macOS) [@DeeDeeG](https://github.com/pulsar-edit/github/pull/13)
|
||||
- Fixed: meta: Revert "main" to "./lib/index", no dist (fix package on `master` branch) [@DeeDeeG](https://github.com/pulsar-edit/github/pull/12)
|
||||
|
||||
## 1.101.0-beta
|
||||
|
||||
- Fixed a bug where macOS menus like "Open" don't do anything
|
||||
- Fixed a bug where macOS wouldn't open files by dragging them onto the dock.
|
||||
- Fixed a bug where devtools won't open (https://github.com/pulsar-edit/pulsar/issues/260)
|
||||
- Fixed a bug where the editor refused to open with the message "GPU process
|
||||
isn't usable. Goodbye" (https://github.com/pulsar-edit/pulsar/issues/233)
|
||||
- Fixed logo artifacts on Linux
|
||||
- Fixed Windows Taskbar Icon being 'Cut in Half'
|
||||
- Fixed commands like `--version`, `--package` or `--help` did not show outputs
|
||||
- Fixed additional flags not being sent to `--package`
|
||||
- Small improvement on the binary size
|
||||
- Fixed "install command line tools" on Mac and Windows
|
||||
- Cached queries for featured packages (featured packages will load faster, and
|
||||
fewer errors on the settings-view regarding package info)
|
||||
- Added warning when `settings-view` is disabled, describing how to re-enable it
|
||||
|
||||
### Pulsar
|
||||
- Added: script: Clean up `pulsar` and `ppm` on uninstall [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/297)
|
||||
- Added: increase search query delay [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/289)
|
||||
- Fixed: update `packages/README.md` [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/317)
|
||||
- Fixed: Fix Windows Icon being cut in half [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/318)
|
||||
- Removed: remove unused json [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/309)
|
||||
- Added: add ignored `package-lock.json` to packages [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/308)
|
||||
- Rebrand: Rebrand AppUserModelID - Ensure Pulsar is separated as its own App Icon on Windows [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/315)
|
||||
- Removed: remove fs-plus from image-view package [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/305)
|
||||
- Added: Additional Bundling of Core Packages [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/314)
|
||||
- Fixed: Resolve some `about` package tests (6 Resolved Tests) [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/310)
|
||||
- Fixed: Fix Package Test Cache Issue [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/302)
|
||||
- Fixed: Resolve all Tests within `language-html` (Resolves 2 Failing Tests) [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/300)
|
||||
- Fixed: Resolve all Tests within `language-javascript` (Resolves 24 Failing Tests) [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/299)
|
||||
- Fixed: Resolve 40 Failing `image-view` Tests [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/293)
|
||||
- Added: Added changelog entries that we missed [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/292)
|
||||
- Removed: meta: Delete preinstall script from package.json [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/296)
|
||||
- Added: Improve macOS Builds [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/280)
|
||||
- Fixed: Fix `archive-view` [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/294)
|
||||
- Added: Improved Windows Builds [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/279)
|
||||
- Added: More Bundles [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/290)
|
||||
- Fixed: Fix macOS open without window [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/291)
|
||||
- Removed: delete workflow from language-java [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/285)
|
||||
- Removed: Remove handlers for opening things on Mac [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/288)
|
||||
- Rebrand: Rebranding and relinking to new site [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/282)
|
||||
- Added: script: symlink ppm in post-install.sh (for .deb and .rpm packages) [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/273)
|
||||
- Added: Add --no-sandbox to start script [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/276)
|
||||
- Added: exclude directories from build [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/265)
|
||||
- Added: add warning when settings-view is disabled [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/243)
|
||||
- Fixed: Fix typo [@snowcatridge10](https://github.com/pulsar-edit/pulsar/pull/267)
|
||||
- Fixed: Fix install on packaged code [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/269)
|
||||
- Fixed: Fix Logo weirdness [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/271)
|
||||
- Fixed: Fix installing shell commands to path (macOS) [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/263)
|
||||
- Fixed: 🍎 Fix wrong app name resolution in pulsar.sh on Mac [@soupertonic](https://github.com/pulsar-edit/pulsar/pull/252)
|
||||
- Fixed: Postinstall error with rm usr/bin/pulsar [@Spiker985](https://github.com/pulsar-edit/pulsar/pull/228)
|
||||
- Added: Made changes to the main.js file. [@CatPerson136](https://github.com/pulsar-edit/pulsar/pull/232)
|
||||
- Added: Add `--no-sandbox` to Linux Launch [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/262)
|
||||
- Removed: removed unused files [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/219)
|
||||
- Rebrand: rebrand package publish domain [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/245)
|
||||
- Removed: remove metrics code from welcome package [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/244)
|
||||
- Fixed: Deep cache for settings view [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/250)
|
||||
- Fixed: fix syntax error in `packages/README.md` [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/248)
|
||||
- Removed: remove package.json dependencies [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/169)
|
||||
- Added: `underscore-plus` to dependencies [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/218)
|
||||
|
||||
### ppm
|
||||
- Added: Convert body params to query params [@Spiker985](https://github.com/pulsar-edit/ppm/pull/47)
|
||||
- Fixed: src: Update Electron header download URL [@DeeDeeG](https://github.com/pulsar-edit/ppm/pull/43)
|
||||
|
||||
## v1.100.0-beta
|
||||
|
||||
- Bump to Electron 12 and Node 14
|
||||
- Added a rebranded API
|
||||
- Added a rebranding API
|
||||
- Removed experimental file watchers on the editor
|
||||
- Ability to install packages from git repositories
|
||||
- New backend
|
||||
- Better error messages when we can't install a package
|
||||
- New Pulsar Package Repository Backend
|
||||
- Better error messages when installing a package fails
|
||||
- Config watching fixes
|
||||
- Bump tree-sitter to 0.20.1 and all grammars to their recent versions
|
||||
- Native support for Apple Silicon
|
||||
- Change Log Window added to Welcome Package
|
||||
- Native support for Apple Silicon and ARM Linux
|
||||
- Removed Benchmark Startup Mode
|
||||
- Removed all telemetry from Core Editor
|
||||
- New Pulsar Website
|
||||
- New Test Runner to Improve Testing
|
||||
- Added Apple Silicon support to `github` Package v0.36.13
|
||||
|
||||
# Atom v1.6.0
|
||||
See https://atom.io/releases
|
||||
### Pulsar
|
||||
- Added: Incorporate settings-view to core [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/220)
|
||||
- Added: Bundle `autocomplete-css` && `autocomplete-html` [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/212)
|
||||
- Added: add or update `packages/*/package-lock.json` [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/209)
|
||||
- Fixed: Organize our Exclusions/Inclusions [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/208)
|
||||
- Added: Bundle `package-generator` [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/207)
|
||||
- Fixed: meta: Don't exclude 'loophole' or 'pegjs' packages [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/206)
|
||||
- Fixed: Fix `dugite` [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/201)
|
||||
- Bumped: ppm: Update ppm submodule (new Electron headers download URL) [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/198)
|
||||
- Removed: Revert "Merge pull request #184 from pulsar-edit/bump-autocomplete-plus" [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/196)
|
||||
- Bumped: Bump GitHub package [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/186)
|
||||
- Fixed: CI (Windows): Use npm (not yarn) to install ppm [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/185)
|
||||
- Bumped: Bumped `autocomplete-plus` [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/184)
|
||||
- Added: Adding test runner missing files [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/183)
|
||||
- Fixed: fix about package test [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/180)
|
||||
- Added: Add tar.gz target to electron-builder [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/178)
|
||||
- Fixed: Cleanup/standardize pulsar.sh [@Spiker985](https://github.com/pulsar-edit/pulsar/pull/175)
|
||||
- Fixed: Update LICENSE.md [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/171)
|
||||
- Removed: remove old scripts [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/168)
|
||||
- Fixed: Fix Codacy Ignore [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/167)
|
||||
- Added: New ChangeLog Format [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/166)
|
||||
- Fixed: shorten task description if too long [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/163)
|
||||
- Fixed: Improve Package Tests [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/161)
|
||||
- Removed: Metric docs from `welcome` [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/159)
|
||||
- Fixed: PostInstall of `ppm` [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/153)
|
||||
- Fixed: Unmerged Menus ignoring separators [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/151)
|
||||
- Removed: `mkdirp` [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/150)
|
||||
- Fixed: `--package` exiting incorrectly [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/149)
|
||||
- Bumped: `ppm` submodule [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/144)
|
||||
- Fixed: undefined `nsole` [@jonian](https://github.com/pulsar-edit/pulsar/pull/142)
|
||||
- Fixed: Git tab in Binaries [@benonymus](https://github.com/pulsar-edit/pulsar/pull/140)
|
||||
- Fixed: `yarn.lock` versions [@jonian](https://github.com/pulsar-edit/pulsar/pull/139)
|
||||
- Added: `dist` & `binaries` to `gitignore` [@jonain](https://github.com/pulsar-edit/pulsar/pull/138)
|
||||
- Bumped: `ppm` submodule to allow Git Package Install [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/131)
|
||||
- Bumped: `settings-view` 0.261.9 -> 0.261.10 [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/130)
|
||||
- Removed: Unused code fragments from build scripts [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/128)
|
||||
- Added: Ability to run `ppm` from `pulsar` CLI [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/125)
|
||||
- Fixed: base16 URL to use WayBack Machine [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/121)
|
||||
- Removed: `fs-plus` from `exception-reporting` [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/118)
|
||||
- Removed: Benchmark Startup Mode Part 2 [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/115)
|
||||
- Removed: Unused scripts [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/114)
|
||||
- Bumped: `background-tips` 0.28.0 -> 0.28.1 [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/111)
|
||||
- Removed: Tooling bloat [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/110)
|
||||
- Bumped: `snippets` NA -> 1.6.1 [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/107)
|
||||
- Removed: Benchmark Startup mode [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/105)
|
||||
- Added: Binaries for Intel Mac & ARM Linux [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/101)
|
||||
- Added: `yarn dist` accepts arguments [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/97)
|
||||
- Fixed: Load core packages `README.md` [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/96)
|
||||
- Fixed: Unlock terminal on Linux [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/82)
|
||||
- Added: Aliases to workflow for link generation [@kaosine](https://github.com/pulsar-edit/pulsar/pull/78)
|
||||
- Fixed: Hooked `NSFW` directly [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/77)
|
||||
- Bumped: `settings-view` 0.261.8 -> 0.261.9 [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/72)
|
||||
- Bumped: `.nvmrc` 12.18 -> 16 [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/71)
|
||||
- Bumped: `ppm` submodule for new backend [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/68)
|
||||
- Removed: Experimental and internal watchers [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/67)
|
||||
- Fixed: Improvements for windows binaries [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/66)
|
||||
- Fixed: Improvements for binary building [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/63)
|
||||
- Bumped: `async` 3.2.0 -> 3.2.4 [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/59)
|
||||
- Removed: Mystery/Ghost Submodule [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/51)
|
||||
- Removed: Telemetry and Remote Crash Reports [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/40)
|
||||
- Added: Bundled `language-c` into the editor [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/33)
|
||||
- Bumped: `electron` 11.5.0 -> 12.2.3 [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/28)
|
||||
- Fixed: `yarn install` due to syntax error [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/16)
|
||||
- Added: Bundled most language grammars into the editor [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/14)
|
||||
- Bumped: `autocomplete-html` 0.8.8 -> 0.8.9 [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/14)
|
||||
- Bumped: `tree-sitter` NA -> 0.20.0 [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/14)
|
||||
- Added: Branding Config on Global Atom API [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/7)
|
||||
- Added: `yarn` as method to build editor. [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/6)
|
||||
- Bumped: `fs-admin` 0.15.0 -> 0.19.0 [@kaosine](https://github.com/pulsar-edit/pulsar/pull/4)
|
||||
- Bumped: `text-buffer` 13.18.5 -> 13.18.6 [@kaosine](https://github.com/pulsar-edit/pulsar/pull/4)
|
||||
- Decaffeinate: Numerous efforts from many contributors to decaffeinate the editor:
|
||||
* [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/112)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/45)
|
||||
* [@Spiker985](https://github.com/pulsar-edit/pulsar/pull/29)
|
||||
* [@fabianfiorotto](https://github.com/pulsar-edit/pulsar/pull/13)
|
||||
- Rebrand: Numerous efforts from many contributors to rebrand the editor:
|
||||
* [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/190)
|
||||
* [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/173)
|
||||
* [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/172)
|
||||
* [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/156)
|
||||
* [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/145)
|
||||
* [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/136)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/126)
|
||||
* [@ElectronicsArchiver](https://github.com/pulsar-edit/pulsar/pull/123)
|
||||
* [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/122)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/120)
|
||||
* [@Sertonix](https://github.com/pulsar-edit/pulsar/pull/103)
|
||||
* [@Daeraxa](https://github.com/pulsar-edit/pulsar/pull/83)
|
||||
* [@Spiker985](https://github.com/pulsar-edit/pulsar/pull/81)
|
||||
* [@kaosine](https://github.com/pulsar-edit/pulsar/pull/65)
|
||||
* [@Spiker985](https://github.com/pulsar-edit/pulsar/pull/58)
|
||||
* [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/54)
|
||||
* [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/22)
|
||||
* [@Spiker985](https://github.com/pulsar-edit/pulsar/pull/17)
|
||||
* [@softcode589](https://github.com/pulsar-edit/pulsar/pull/11)
|
||||
* [@LandarXT](https://github.com/pulsar-edit/pulsar/pull/10)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/8)
|
||||
- Tests: Numerous efforts from many contributors to improve our tests:
|
||||
* [@icecream17](https://github.com/pulsar-edit/pulsar/pull/152)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/141)
|
||||
* [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/116)
|
||||
* [@Spiker985](https://github.com/pulsar-edit/pulsar/pull/109)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/70)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/50)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/48)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/46)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/42)
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/41)
|
||||
* [@fabianfiorotto](https://github.com/pulsar-edit/pulsar/pull/36)
|
||||
* [@fabianfiorotto](https://github.com/pulsar-edit/pulsar/pull/35)
|
||||
* [@mauricioszabo](https://github.com/pulsar-edit/pulsar/pull/18)
|
||||
|
||||
### ppm
|
||||
- Fixed: ppm PostInstall [@mauricioszabo](https://github.com/pulsar-edit/ppm/pull/41)
|
||||
- Added: Better `help` command display [@mauricioszabo](https://github.com/pulsar-edit/ppm/pull/40)
|
||||
- Fixed: Empty Featured Packages [@jonian](https://github.com/pulsar-edit/ppm/pull/38)
|
||||
- Fixed: Use ppm as basename in `getResourcePath` [@jonain](https://github.com/pulsar-edit/ppm/pull/36)
|
||||
- Fixed: Installation from Git [@mauricioszabo](https://github.com/pulsar-edit/ppm/pull/34)
|
||||
- Added: Ability to define tag to install [@mauricioszabo](https://github.com/pulsar-edit/ppm/pull/13)
|
||||
- Added: Our new Pulsar Package Repository Backend [@confused-Techie](https://github.com/pulsar-edit/ppm/pull/5)
|
||||
- Bumped: `electron` to 12 [@mauricioszabo](https://github.com/pulsar-edit/ppm/pull/2)
|
||||
- Rebrand: Numerous efforts from many contributors to rebrand ppm:
|
||||
* [@Sertonix](https://github.com/pulsar-edit/ppm/pull/12)
|
||||
* [@softcode589](https://github.com/pulsar-edit/ppm/pull/7)
|
||||
* [@mauricioszabo](https://github.com/pulsar-edit/ppm/pull/6)
|
||||
- Tests: Numerous efforts from many contributors to improve our tests:
|
||||
* [@DeeDeeG](https://github.com/pulsar-edit/ppm/pull/39)
|
||||
|
||||
### autocomplete-html
|
||||
- Fixed: Finding the proper Node version [@mauricioszabo](https://github.com/pulsar-edit/autocomplete-html/pull/1)
|
||||
|
||||
### settings-view
|
||||
- Added: Remember Scroll Position [@jonian](https://github.com/pulsar-edit/settings-view/pull/12)
|
||||
- Removed: Support for deprecated packages [@Sertonix](https://github.com/pulsar-edit/settings-view/pull/6)
|
||||
- Added: Better errors when search fails [@mauricioszabo](https://github.com/pulsar-edit/settings-view/pull/2)
|
||||
- Rebrand: Numerous efforts from many contributors to rebrand settings-view:
|
||||
* [@mauricioszabo](https://github.com/pulsar-edit/settings-view/pull/7)
|
||||
* [@softcode589](https://github.com/pulsar-edit/settings-view/pull/3)
|
||||
* [@mauricioszabo](https://github.com/pulsar-edit/settings-view/pull/1)
|
||||
- Tests: Numerous efforts from many contributors to improve our tests:
|
||||
* [@confused-Techie](https://github.com/pulsar-edit/settings-view/pull/10)
|
||||
|
||||
### snippets
|
||||
- Added: Proper Testing [@confused-Techie](https://github.com/pulsar-edit/snippets/pull/4)
|
||||
- Removed: `fs-plus` [@Sertonix](https://github.com/pulsar-edit/snippets/pull/2)
|
||||
- Fixed: Fix open Snippets URI [@Sertonix](https://github.com/pulsar-edit/snippets/pull/1)
|
||||
|
||||
### background-tips
|
||||
- Bumped: `background-tips` 0.28.0 -> 0.28.1 [@confused-Techie](https://github.com/pulsar-edit/background-tips/pull/4)
|
||||
- Rebrand: Numerous efforts from many contributors to rebrand background-tips:
|
||||
* [@Sertonix](https://github.com/pulsar-edit/background-tips/pull/5)
|
||||
* [@Sertonix](https://github.com/pulsar-edit/background-tips/pull/2)
|
||||
* [@Sertonix](https://github.com/pulsar-edit/background-tips/pull/1)
|
||||
|
||||
|
||||
## Atom v1.6.0
|
||||
|
||||
- See https://atom.io/releases
|
||||
|
@ -1,5 +1,5 @@
|
||||
# VERSION: 0.2
|
||||
# DESCRIPTION: Image to build Atom
|
||||
# DESCRIPTION: Image to build Pulsar
|
||||
|
||||
FROM ubuntu:20.04
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Pulsar-Edit
|
||||
Copyright (c) 2022-2023 Pulsar-Edit
|
||||
Original work copyright (c) 2011-2022 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
10
README.md
10
README.md
@ -26,12 +26,13 @@
|
||||
|
||||
<br>
|
||||
|
||||
*A Community-led Hyper-Hackable Text Editor, built on **[Electron]**,*
|
||||
*and based on everything we love about our favorite editors.*
|
||||
*A Community-led Hyper-Hackable Text Editor,*
|
||||
*Forked from [Atom], built on [Electron].*
|
||||
|
||||
*We designed it to be deeply customizable, but still*
|
||||
*Designed to be deeply customizable, but still*
|
||||
*approachable using the default configuration.*
|
||||
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
@ -44,6 +45,7 @@
|
||||
[OpenCollective]: https://opencollective.com/pulsar-edit
|
||||
[Discussions]: https://github.com/orgs/pulsar-edit/discussions
|
||||
[Electron]: https://github.com/electron/electron
|
||||
[Atom]: https://github.blog/2022-06-08-sunsetting-atom/
|
||||
[Discord]: https://discord.gg/7aEbB9dGRT 'Join the Pulsar Discord today!'
|
||||
[Crowdin]: https://crowdin.pulsar-edit.dev
|
||||
[Status]: https://cirrus-ci.com/github/pulsar-edit/pulsar/master
|
||||
@ -64,7 +66,7 @@
|
||||
|
||||
<!---------------------------{ Images }--------------------------->
|
||||
|
||||
[Preview]: https://user-images.githubusercontent.com/378023/49132478-f4b77680-f31f-11e8-9e10-e8454d8d9b7e.png 'Preview of the editor.'
|
||||
[Preview]: resources/readme.png 'Preview of the editor.'
|
||||
|
||||
|
||||
<!---------------------------{ Badges }--------------------------->
|
||||
|
11
docs/.jsdoc.json
Normal file
11
docs/.jsdoc.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"recurseDepth": 10,
|
||||
"source": {
|
||||
"include": ["src", "packages"],
|
||||
"exclude": ["node_modules"],
|
||||
"excludePattern": "((^|\\/|\\\\)_|node_modules)"
|
||||
},
|
||||
"opts": {
|
||||
"recurse": true
|
||||
}
|
||||
}
|
298
docs/Pulsar-API-Documentation.md
Normal file
298
docs/Pulsar-API-Documentation.md
Normal file
@ -0,0 +1,298 @@
|
||||
## Classes
|
||||
|
||||
<dl>
|
||||
<dt><a href="#AtomEnvironment">AtomEnvironment</a></dt>
|
||||
<dd><p>Pulsar global for dealing with packages, themes, menus, and the window.</p>
|
||||
<p>An instance of this class is always available as the <code>atom</code> global.</p>
|
||||
</dd>
|
||||
<dt><a href="#Clipboard">Clipboard</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
## Constants
|
||||
|
||||
<dl>
|
||||
<dt><a href="#etch">etch</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#fs">fs</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#dalek">dalek</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#assert">assert</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
## Functions
|
||||
|
||||
<dl>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#conditionPromise">conditionPromise()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#destroy">destroy()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#destroyChildren">destroyChildren()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#releaseChildren">releaseChildren()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#subscribeToRepository">subscribeToRepository()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#updateDiffs">updateDiffs()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#conditionPromise">conditionPromise()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
<a name="AtomEnvironment"></a>
|
||||
|
||||
## AtomEnvironment
|
||||
Pulsar global for dealing with packages, themes, menus, and the window.
|
||||
|
||||
An instance of this class is always available as the `atom` global.
|
||||
|
||||
**Kind**: global class
|
||||
|
||||
* [AtomEnvironment](#AtomEnvironment)
|
||||
* _instance_
|
||||
* [.clipboard](#AtomEnvironment+clipboard) : [<code>Clipboard</code>](#Clipboard)
|
||||
* [.deserializers](#AtomEnvironment+deserializers) : <code>DeserializerManager</code>
|
||||
* [.views](#AtomEnvironment+views) : <code>ViewRegistry</code>
|
||||
* [.notifications](#AtomEnvironment+notifications) : <code>NotificationManager</code>
|
||||
* [.config](#AtomEnvironment+config) : <code>Config</code>
|
||||
* [.keymaps](#AtomEnvironment+keymaps) : <code>KeymapManager</code>
|
||||
* [.tooltips](#AtomEnvironment+tooltips) : <code>TooltipManager</code>
|
||||
* [.commands](#AtomEnvironment+commands) : <code>CommandRegistry</code>
|
||||
* [.grammars](#AtomEnvironment+grammars) : <code>GrammarRegistry</code>
|
||||
* [.styles](#AtomEnvironment+styles) : <code>StyleManager</code>
|
||||
* [.packages](#AtomEnvironment+packages) : <code>PackageManager</code>
|
||||
* [.themes](#AtomEnvironment+themes) : <code>ThemeManager</code>
|
||||
* [.menu](#AtomEnvironment+menu) : <code>MenuManager</code>
|
||||
* [.contextMenu](#AtomEnvironment+contextMenu) : <code>ContextMenuManager</code>
|
||||
* [.project](#AtomEnvironment+project) : <code>Project</code>
|
||||
* [.textEditors](#AtomEnvironment+textEditors) : <code>TextEditorRegistry</code>
|
||||
* [.workspace](#AtomEnvironment+workspace) : <code>Workspace</code>
|
||||
* [.history](#AtomEnvironment+history) : <code>HistoryManager</code>
|
||||
* _Messaging the User_
|
||||
* [.beep()](#AtomEnvironment+beep)
|
||||
* _static_
|
||||
* _Event Subscription_
|
||||
* [.onDidBeep(callback)](#AtomEnvironment.onDidBeep) ⇒ <code>Disposable</code>
|
||||
|
||||
<a name="AtomEnvironment+clipboard"></a>
|
||||
|
||||
### atomEnvironment.clipboard : [<code>Clipboard</code>](#Clipboard)
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+deserializers"></a>
|
||||
|
||||
### atomEnvironment.deserializers : <code>DeserializerManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+views"></a>
|
||||
|
||||
### atomEnvironment.views : <code>ViewRegistry</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+notifications"></a>
|
||||
|
||||
### atomEnvironment.notifications : <code>NotificationManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+config"></a>
|
||||
|
||||
### atomEnvironment.config : <code>Config</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+keymaps"></a>
|
||||
|
||||
### atomEnvironment.keymaps : <code>KeymapManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+tooltips"></a>
|
||||
|
||||
### atomEnvironment.tooltips : <code>TooltipManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+commands"></a>
|
||||
|
||||
### atomEnvironment.commands : <code>CommandRegistry</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+grammars"></a>
|
||||
|
||||
### atomEnvironment.grammars : <code>GrammarRegistry</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+styles"></a>
|
||||
|
||||
### atomEnvironment.styles : <code>StyleManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+packages"></a>
|
||||
|
||||
### atomEnvironment.packages : <code>PackageManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+themes"></a>
|
||||
|
||||
### atomEnvironment.themes : <code>ThemeManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+menu"></a>
|
||||
|
||||
### atomEnvironment.menu : <code>MenuManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+contextMenu"></a>
|
||||
|
||||
### atomEnvironment.contextMenu : <code>ContextMenuManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+project"></a>
|
||||
|
||||
### atomEnvironment.project : <code>Project</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+textEditors"></a>
|
||||
|
||||
### atomEnvironment.textEditors : <code>TextEditorRegistry</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+workspace"></a>
|
||||
|
||||
### atomEnvironment.workspace : <code>Workspace</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+history"></a>
|
||||
|
||||
### atomEnvironment.history : <code>HistoryManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+beep"></a>
|
||||
|
||||
### atomEnvironment.beep()
|
||||
Visually and audibly trigger a beep.
|
||||
|
||||
**Kind**: instance method of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
**Category**: Messaging the User
|
||||
**Emits**: <code>event:beep</code>
|
||||
<a name="AtomEnvironment.onDidBeep"></a>
|
||||
|
||||
### AtomEnvironment.onDidBeep(callback) ⇒ <code>Disposable</code>
|
||||
Invoke the given callback whenever [::beep](::beep) is called.
|
||||
|
||||
**Kind**: static method of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
**Returns**: <code>Disposable</code> - on which `.dispose()` can be called to unsubscribe.
|
||||
**Category**: Event Subscription
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| callback | <code>function</code> | Function to be called whenever [::beep](::beep) is called. |
|
||||
|
||||
<a name="Clipboard"></a>
|
||||
|
||||
## Clipboard
|
||||
**Kind**: global class
|
||||
<a name="new_Clipboard_new"></a>
|
||||
|
||||
### new Clipboard()
|
||||
Represents the clipboard used for copying and pasting in Pulsar.
|
||||
|
||||
An instance of this class is always available as the `atom.clipboard` global.
|
||||
|
||||
**Example**
|
||||
```js
|
||||
// returns 'hello'
|
||||
atom.clipboard.write('hello');
|
||||
|
||||
console.log(atom.clipboard.read());
|
||||
```
|
||||
<a name="etch"></a>
|
||||
|
||||
## etch
|
||||
**Kind**: global constant
|
||||
**Jsx**: etch.dom
|
||||
<a name="fs"></a>
|
||||
|
||||
## fs
|
||||
**Kind**: global constant
|
||||
**Babel**:
|
||||
<a name="dalek"></a>
|
||||
|
||||
## dalek
|
||||
**Kind**: global constant
|
||||
**Babel**:
|
||||
<a name="assert"></a>
|
||||
|
||||
## assert
|
||||
**Kind**: global constant
|
||||
**Babel**:
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="conditionPromise"></a>
|
||||
|
||||
## conditionPromise()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="destroy"></a>
|
||||
|
||||
## destroy()
|
||||
**Kind**: global function
|
||||
**Describe**: Handles tear down of destructables and subscriptions.
|
||||
Does not handle release of memory. This method should only be called
|
||||
just before this object is freed, and should only tear down the main
|
||||
object components that are guarunteed to exist at all times.
|
||||
<a name="destroyChildren"></a>
|
||||
|
||||
## destroyChildren()
|
||||
**Kind**: global function
|
||||
**Describe**: Destroys this objects children (non-freeing), it's intended
|
||||
to be an ease-of use function for maintaing this object. This method
|
||||
should only tear down objects that are selectively allocated upon
|
||||
repository discovery.
|
||||
|
||||
Example: this.diffs only exists when we have a repository.
|
||||
<a name="releaseChildren"></a>
|
||||
|
||||
## releaseChildren()
|
||||
**Kind**: global function
|
||||
**Describe**: The memory releasing complement function of `destroyChildren`.
|
||||
frees the memory allocated at all child object storage locations
|
||||
when there is no repository.
|
||||
<a name="subscribeToRepository"></a>
|
||||
|
||||
## subscribeToRepository()
|
||||
**Kind**: global function
|
||||
**Describe**: handles all subscriptions based on the repository in focus
|
||||
<a name="updateDiffs"></a>
|
||||
|
||||
## updateDiffs()
|
||||
**Kind**: global function
|
||||
**Describe**: Uses text markers in the target editor to visualize
|
||||
git modifications, additions, and deletions. The current algorithm
|
||||
just redraws the markers each call.
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="conditionPromise"></a>
|
||||
|
||||
## conditionPromise()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
306
docs/Source-Code-Documentation.md
Normal file
306
docs/Source-Code-Documentation.md
Normal file
@ -0,0 +1,306 @@
|
||||
## Classes
|
||||
|
||||
<dl>
|
||||
<dt><a href="#AtomEnvironment">AtomEnvironment</a></dt>
|
||||
<dd><p>Pulsar global for dealing with packages, themes, menus, and the window.</p>
|
||||
<p>An instance of this class is always available as the <code>atom</code> global.</p>
|
||||
</dd>
|
||||
<dt><a href="#Clipboard">Clipboard</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
## Constants
|
||||
|
||||
<dl>
|
||||
<dt><a href="#etch">etch</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#fs">fs</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#dalek">dalek</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#assert">assert</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
## Functions
|
||||
|
||||
<dl>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#conditionPromise">conditionPromise()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#destroy">destroy()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#destroyChildren">destroyChildren()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#releaseChildren">releaseChildren()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#subscribeToRepository">subscribeToRepository()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#updateDiffs">updateDiffs()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#conditionPromise">conditionPromise()</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#beforeEach">beforeEach()</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
<a name="AtomEnvironment"></a>
|
||||
|
||||
## AtomEnvironment
|
||||
Pulsar global for dealing with packages, themes, menus, and the window.
|
||||
|
||||
An instance of this class is always available as the `atom` global.
|
||||
|
||||
**Kind**: global class
|
||||
|
||||
* [AtomEnvironment](#AtomEnvironment)
|
||||
* _instance_
|
||||
* [.clipboard](#AtomEnvironment+clipboard) : [<code>Clipboard</code>](#Clipboard)
|
||||
* [.deserializers](#AtomEnvironment+deserializers) : <code>DeserializerManager</code>
|
||||
* [.views](#AtomEnvironment+views) : <code>ViewRegistry</code>
|
||||
* [.notifications](#AtomEnvironment+notifications) : <code>NotificationManager</code>
|
||||
* [.config](#AtomEnvironment+config) : <code>Config</code>
|
||||
* [.keymaps](#AtomEnvironment+keymaps) : <code>KeymapManager</code>
|
||||
* [.tooltips](#AtomEnvironment+tooltips) : <code>TooltipManager</code>
|
||||
* [.commands](#AtomEnvironment+commands) : <code>CommandRegistry</code>
|
||||
* [.grammars](#AtomEnvironment+grammars) : <code>GrammarRegistry</code>
|
||||
* [.styles](#AtomEnvironment+styles) : <code>StyleManager</code>
|
||||
* [.packages](#AtomEnvironment+packages) : <code>PackageManager</code>
|
||||
* [.themes](#AtomEnvironment+themes) : <code>ThemeManager</code>
|
||||
* [.menu](#AtomEnvironment+menu) : <code>MenuManager</code>
|
||||
* [.contextMenu](#AtomEnvironment+contextMenu) : <code>ContextMenuManager</code>
|
||||
* [.project](#AtomEnvironment+project) : <code>Project</code>
|
||||
* [.textEditors](#AtomEnvironment+textEditors) : <code>TextEditorRegistry</code>
|
||||
* [.workspace](#AtomEnvironment+workspace) : <code>Workspace</code>
|
||||
* [.history](#AtomEnvironment+history) : <code>HistoryManager</code>
|
||||
* _Messaging the User_
|
||||
* [.beep()](#AtomEnvironment+beep)
|
||||
* _static_
|
||||
* [.preloadPackages](#AtomEnvironment.preloadPackages) ℗
|
||||
* _Event Subscription_
|
||||
* [.onDidBeep(callback)](#AtomEnvironment.onDidBeep) ⇒ <code>Disposable</code>
|
||||
|
||||
<a name="AtomEnvironment+clipboard"></a>
|
||||
|
||||
### atomEnvironment.clipboard : [<code>Clipboard</code>](#Clipboard)
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+deserializers"></a>
|
||||
|
||||
### atomEnvironment.deserializers : <code>DeserializerManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+views"></a>
|
||||
|
||||
### atomEnvironment.views : <code>ViewRegistry</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+notifications"></a>
|
||||
|
||||
### atomEnvironment.notifications : <code>NotificationManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+config"></a>
|
||||
|
||||
### atomEnvironment.config : <code>Config</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+keymaps"></a>
|
||||
|
||||
### atomEnvironment.keymaps : <code>KeymapManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+tooltips"></a>
|
||||
|
||||
### atomEnvironment.tooltips : <code>TooltipManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+commands"></a>
|
||||
|
||||
### atomEnvironment.commands : <code>CommandRegistry</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+grammars"></a>
|
||||
|
||||
### atomEnvironment.grammars : <code>GrammarRegistry</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+styles"></a>
|
||||
|
||||
### atomEnvironment.styles : <code>StyleManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+packages"></a>
|
||||
|
||||
### atomEnvironment.packages : <code>PackageManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+themes"></a>
|
||||
|
||||
### atomEnvironment.themes : <code>ThemeManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+menu"></a>
|
||||
|
||||
### atomEnvironment.menu : <code>MenuManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+contextMenu"></a>
|
||||
|
||||
### atomEnvironment.contextMenu : <code>ContextMenuManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+project"></a>
|
||||
|
||||
### atomEnvironment.project : <code>Project</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+textEditors"></a>
|
||||
|
||||
### atomEnvironment.textEditors : <code>TextEditorRegistry</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+workspace"></a>
|
||||
|
||||
### atomEnvironment.workspace : <code>Workspace</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+history"></a>
|
||||
|
||||
### atomEnvironment.history : <code>HistoryManager</code>
|
||||
**Kind**: instance property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
<a name="AtomEnvironment+beep"></a>
|
||||
|
||||
### atomEnvironment.beep()
|
||||
Visually and audibly trigger a beep.
|
||||
|
||||
**Kind**: instance method of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
**Category**: Messaging the User
|
||||
**Emits**: <code>event:beep</code>
|
||||
<a name="AtomEnvironment.preloadPackages"></a>
|
||||
|
||||
### AtomEnvironment.preloadPackages ℗
|
||||
Returns output of `preloadPackages()` for this Classes Instance of `Packages`.
|
||||
|
||||
**Kind**: static property of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
**Access**: private
|
||||
<a name="AtomEnvironment.onDidBeep"></a>
|
||||
|
||||
### AtomEnvironment.onDidBeep(callback) ⇒ <code>Disposable</code>
|
||||
Invoke the given callback whenever [::beep](::beep) is called.
|
||||
|
||||
**Kind**: static method of [<code>AtomEnvironment</code>](#AtomEnvironment)
|
||||
**Returns**: <code>Disposable</code> - on which `.dispose()` can be called to unsubscribe.
|
||||
**Category**: Event Subscription
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| callback | <code>function</code> | Function to be called whenever [::beep](::beep) is called. |
|
||||
|
||||
<a name="Clipboard"></a>
|
||||
|
||||
## Clipboard
|
||||
**Kind**: global class
|
||||
<a name="new_Clipboard_new"></a>
|
||||
|
||||
### new Clipboard()
|
||||
Represents the clipboard used for copying and pasting in Pulsar.
|
||||
|
||||
An instance of this class is always available as the `atom.clipboard` global.
|
||||
|
||||
**Example**
|
||||
```js
|
||||
// returns 'hello'
|
||||
atom.clipboard.write('hello');
|
||||
|
||||
console.log(atom.clipboard.read());
|
||||
```
|
||||
<a name="etch"></a>
|
||||
|
||||
## etch
|
||||
**Kind**: global constant
|
||||
**Jsx**: etch.dom
|
||||
<a name="fs"></a>
|
||||
|
||||
## fs
|
||||
**Kind**: global constant
|
||||
**Babel**:
|
||||
<a name="dalek"></a>
|
||||
|
||||
## dalek
|
||||
**Kind**: global constant
|
||||
**Babel**:
|
||||
<a name="assert"></a>
|
||||
|
||||
## assert
|
||||
**Kind**: global constant
|
||||
**Babel**:
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="conditionPromise"></a>
|
||||
|
||||
## conditionPromise()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="destroy"></a>
|
||||
|
||||
## destroy()
|
||||
**Kind**: global function
|
||||
**Describe**: Handles tear down of destructables and subscriptions.
|
||||
Does not handle release of memory. This method should only be called
|
||||
just before this object is freed, and should only tear down the main
|
||||
object components that are guarunteed to exist at all times.
|
||||
<a name="destroyChildren"></a>
|
||||
|
||||
## destroyChildren()
|
||||
**Kind**: global function
|
||||
**Describe**: Destroys this objects children (non-freeing), it's intended
|
||||
to be an ease-of use function for maintaing this object. This method
|
||||
should only tear down objects that are selectively allocated upon
|
||||
repository discovery.
|
||||
|
||||
Example: this.diffs only exists when we have a repository.
|
||||
<a name="releaseChildren"></a>
|
||||
|
||||
## releaseChildren()
|
||||
**Kind**: global function
|
||||
**Describe**: The memory releasing complement function of `destroyChildren`.
|
||||
frees the memory allocated at all child object storage locations
|
||||
when there is no repository.
|
||||
<a name="subscribeToRepository"></a>
|
||||
|
||||
## subscribeToRepository()
|
||||
**Kind**: global function
|
||||
**Describe**: handles all subscriptions based on the repository in focus
|
||||
<a name="updateDiffs"></a>
|
||||
|
||||
## updateDiffs()
|
||||
**Kind**: global function
|
||||
**Describe**: Uses text markers in the target editor to visualize
|
||||
git modifications, additions, and deletions. The current algorithm
|
||||
just redraws the markers each call.
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="conditionPromise"></a>
|
||||
|
||||
## conditionPromise()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
||||
<a name="beforeEach"></a>
|
||||
|
||||
## beforeEach()
|
||||
**Kind**: global function
|
||||
**Babel**:
|
@ -11,3 +11,7 @@
|
||||
// console.log(`Saved! ${editor.getPath()}`)
|
||||
// )
|
||||
// );
|
||||
//
|
||||
// See the Pulsar Launch manual for more information on this file and how to
|
||||
// customize it.
|
||||
// https://pulsar-edit.dev/docs/launch-manual/sections/core-hacking/#the-init-file
|
||||
|
@ -18,15 +18,15 @@
|
||||
# 'ctrl-p': 'core:move-down'
|
||||
#
|
||||
# You can find more information about keymaps in these guides:
|
||||
# * http://flight-manual.atom.io/using-atom/sections/basic-customization/#customizing-keybindings
|
||||
# * http://flight-manual.atom.io/behind-atom/sections/keymaps-in-depth/
|
||||
# * https://pulsar-edit.dev/docs/launch-manual/sections/using-pulsar/#customizing-keybindings
|
||||
# * https://pulsar-edit.dev/docs/launch-manual/sections/behind-pulsar#keymaps-in-depth
|
||||
#
|
||||
# If you're having trouble with your keybindings not working, try the
|
||||
# Keybinding Resolver: `Cmd+.` on macOS and `Ctrl+.` on other platforms. See the
|
||||
# Debugging Guide for more information:
|
||||
# * http://flight-manual.atom.io/hacking-atom/sections/debugging/#check-the-keybindings
|
||||
# * https://pulsar-edit.dev/docs/launch-manual/sections/core-hacking/#check-your-keybindings
|
||||
#
|
||||
# This file uses CoffeeScript Object Notation (CSON).
|
||||
# If you are unfamiliar with CSON, you can read more about it in the
|
||||
# Pulsar Flight Manual:
|
||||
# http://flight-manual.atom.io/using-atom/sections/basic-customization/#configuring-with-cson
|
||||
# Pulsar Launch Manual:
|
||||
# https://pulsar-edit.dev/docs/launch-manual/sections/using-pulsar/#configuring-with-cson
|
||||
|
@ -17,5 +17,5 @@
|
||||
#
|
||||
# This file uses CoffeeScript Object Notation (CSON).
|
||||
# If you are unfamiliar with CSON, you can read more about it in the
|
||||
# Pulsar Flight Manual:
|
||||
# http://flight-manual.atom.io/using-atom/sections/basic-customization/#_cson
|
||||
# Pulsar Launch Manual:
|
||||
# https://pulsar-edit.dev/docs/launch-manual/sections/using-pulsar/#configuring-with-cson
|
||||
|
@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Your Stylesheet
|
||||
*
|
||||
* This stylesheet is loaded when Atom starts up and is reloaded automatically
|
||||
* This stylesheet is loaded when Pulsar starts up and is reloaded automatically
|
||||
* when it is changed and saved.
|
||||
*
|
||||
* Add your own CSS or Less to fully customize Atom.
|
||||
* Add your own CSS or Less to fully customize Pulsar.
|
||||
* If you are unfamiliar with Less, you can read more about it here:
|
||||
* http://lesscss.org
|
||||
*/
|
||||
|
25
hooks/README.md
Normal file
25
hooks/README.md
Normal file
@ -0,0 +1,25 @@
|
||||
### Contents
|
||||
| Filename | Description |
|
||||
| - | - |
|
||||
| post-checkout | This hook executes after a branch checkout, or branch switch has occurred. |
|
||||
| post-merge | This hook executes after a branch merge has occurred |
|
||||
| update_editor.sh | The actual brains of the hooks. Performs a yarn install, yarn build, yarn build:apm, and syncs all submodules. |
|
||||
|
||||
### Disclaimer
|
||||
These hooks are not guaranteed. These were made out of convenience and presented to the org as an optional tool for usage.
|
||||
|
||||
### Usage
|
||||
There are several ways to apply these hooks:
|
||||
- You can manually copy the files over to the `<pulsar-repo-root>/.git/hooks` folder and validate that they are executable - the effect should be immediate. This is the preferred option for Windows.
|
||||
- You can use manage_hooks.sh to copy/symlink the hooks you choose. This is the preferred option for Linux/macOS.
|
||||
- Your mileage may vary on macOS as it has not been tested outright, but should work in theory.
|
||||
|
||||
### Instructions
|
||||
- Open your favorite terminal
|
||||
- Navigate to `<pulsar-repo-root>/hooks`.
|
||||
- IMPORTANT: The bash completions will only work within this directory, and are activated when using exactly `./manage-hooks.sh`.
|
||||
- If you have bash-completions, source the `manage_hooks-completion.bash` file to allow for auto-complete ie `source manage_hooks-completion.bash`.
|
||||
- Allow the auto-complete responses to guide you.
|
||||
- Standard commands are `list`, `install` and `remove`
|
||||
- The `install` and `remove` commands require the hook you wish to install, followed by an optional parameter for `copy` vs `symlink` with symlink being the default.
|
||||
- A symbolically linked hook allows you to receive updates in the future. If you plan on adjusting your hook(s), you probably want to `copy` the files to the `<pulsar-repo-root>/.git/hooks` directory
|
59
hooks/manage_hooks-completion.bash
Normal file
59
hooks/manage_hooks-completion.bash
Normal file
@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
|
||||
#Not gonna lie, this is some magical stuff, but I will try to explain it
|
||||
|
||||
#Automatic variables used by complete
|
||||
#COMPREPLY = An array of autocompletions to pass back to the shell
|
||||
#COMP_WORDS = The passed-in list of parameters
|
||||
#COMP_CWORD = The index of the current word as related to the count of
|
||||
#parameters
|
||||
|
||||
#compgen = Generates an array of autocompletions to pass back to the shell
|
||||
#based on provided parameters
|
||||
|
||||
function __completion() {
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts="list install remove"
|
||||
|
||||
#Determine what "level" of autocomplete we are operating on
|
||||
#1 is no params
|
||||
#2 is 1 param, in this instance the command
|
||||
#3 etc
|
||||
case ${COMP_CWORD} in
|
||||
1)
|
||||
#Generate a Word-list from opts from the current word
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
;;
|
||||
2)
|
||||
case ${prev} in
|
||||
install)
|
||||
#Generate a list of filenames (and append "all") based on the current
|
||||
#directory and current word while ignoring select files
|
||||
COMPREPLY=( $(compgen -W "all $(ls --ignore='*.md' --ignore='*.sh' --ignore='*.bash')" -- ${cur}) )
|
||||
;;
|
||||
remove)
|
||||
#Generate a list of filenames (and append "all") based on the
|
||||
#.git/hooks directory and current word while ignoring the sample
|
||||
#files
|
||||
COMPREPLY=( $(compgen -W "all $(ls ../.git/hooks --ignore='*.sample')" -- ${cur}) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
3)
|
||||
case "${COMP_WORDS[COMP_CWORD-2]}" in
|
||||
install)
|
||||
#When attempting to autocomplete for the third parameter ie copy
|
||||
#/symbolic AND the command is install
|
||||
#Generate a list of Words from the provded string
|
||||
COMPREPLY=( $(compgen -W "copy symbolic" -- ${cur}) )
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
#Use the function defined above, when an autocomplete event for
|
||||
#./manage_hooks.sh is fired. This is why you must be in the proper directory
|
||||
complete -F __completion ./manage_hooks.sh
|
83
hooks/manage_hooks.sh
Executable file
83
hooks/manage_hooks.sh
Executable file
@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
|
||||
USAGEMSG="Usage: manage_hooks <action> <hook> <option>"
|
||||
|
||||
if [[ $# -lt 1 ]] || [[ $# -gt 3 ]]; then
|
||||
echo "$USAGEMSG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
action="$1"
|
||||
|
||||
case $1 in
|
||||
list)
|
||||
ls --color=if-tty -l ../.git/hooks --ignore='*.sample'
|
||||
;;
|
||||
|
||||
install)
|
||||
#Grab our list of files if all was passed.
|
||||
#Couldn't get * to function without globbing
|
||||
if [[ "$2" == "all" ]]; then
|
||||
hooks=( $(readlink -f $(ls --ignore='*.md' --ignore='*.sh' --ignore='*.bash')) )
|
||||
else
|
||||
hooks=( $(readlink -f "$2") )
|
||||
fi
|
||||
|
||||
#Default to symbolic
|
||||
if [[ -z $3 ]]; then
|
||||
option="symbolic"
|
||||
else
|
||||
option="$3"
|
||||
fi
|
||||
|
||||
case $option in
|
||||
copy)
|
||||
#If copying, copy the update_editor file as well
|
||||
hooks+=( "$(readlink -f "update_editor.sh")" "${hooks[@]}" )
|
||||
|
||||
for hook in "${hooks[@]}"; do
|
||||
#If the file doesnt already exist copy it over
|
||||
if [[ ! -f "../.git/hooks/$(basename "$hook")" ]]; then
|
||||
echo "$hook"
|
||||
cp "$hook" "../.git/hooks"
|
||||
fi
|
||||
done
|
||||
;;
|
||||
|
||||
symbolic)
|
||||
#Switch to the git hook directory, because symlink hooks are required
|
||||
#to be relative
|
||||
cd "../.git/hooks"
|
||||
|
||||
for hook in "${hooks[@]}"; do
|
||||
#If the file doesnt already exist, symlink it
|
||||
if [[ ! -f "$(basename $hook)" ]]; then
|
||||
echo "$(readlink -f .)/$(basename $hook)"
|
||||
ln --symbolic --relative "../../hooks/$(basename "$hook")"
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
remove)
|
||||
#Switch to the git hook directory, so we dont have to deal with
|
||||
#relative file paths
|
||||
cd "../.git/hooks"
|
||||
|
||||
#Grab the canonical path to the file, readlink always follows symlinks
|
||||
if [[ "$2" == "all" ]]; then
|
||||
hooks=( $(realpath --no-symlinks $(ls --ignore='*.sample' --ignore='*.sh')) )
|
||||
else
|
||||
hooks=( $(realpath --no-symlinks "$2") )
|
||||
fi
|
||||
|
||||
for hook in "${hooks[@]}"; do
|
||||
echo "$hook"
|
||||
rm "$hook"
|
||||
done
|
||||
;;
|
||||
*)
|
||||
echo "$USAGEMSG"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
24
hooks/post-checkout
Executable file
24
hooks/post-checkout
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
#This hook launches after a branch change, or branch checkout. It cannot affect
|
||||
#the outcome of a git switch or git checkout with the exception that the hook
|
||||
#exit status becomes the exit status of the antecedent command
|
||||
#See https://git-scm.com/docs/githooks#_post_checkout
|
||||
|
||||
if [[ -L "$0" ]]; then
|
||||
#If our launched script is a link, grab the root
|
||||
hookRoot="$(dirname $(readlink --canonicalize "$0"))"
|
||||
else
|
||||
#Otherwise use the launched script directory
|
||||
hookRoot="$(dirname "$0")"
|
||||
fi
|
||||
|
||||
if [[ "$1" == "$2" ]]; then
|
||||
#Previous HEAD and new HEAD are the same, ignore
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$3" == '1' ]]; then
|
||||
#A branch checkout will always be flagged as 1, and a file checkout as 0
|
||||
"${hookRoot}/update_editor.sh" $0
|
||||
fi
|
15
hooks/post-merge
Executable file
15
hooks/post-merge
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
#This hook launches after a git pull. It cannot affect a git merge, and will not
|
||||
#be executed if a merge fails
|
||||
#See https://git-scm.com/docs/githooks#_post_merge
|
||||
|
||||
if [[ -L "$0" ]]; then
|
||||
#If our launched script is a link, grab the root
|
||||
hookRoot="$(dirname $(readlink --canonicalize $0))"
|
||||
else
|
||||
#Otherwise use the launched script directory
|
||||
hookRoot="$(dirname "$0")"
|
||||
fi
|
||||
|
||||
"${hookRoot}/update_editor.sh" $0
|
56
hooks/update_editor.sh
Executable file
56
hooks/update_editor.sh
Executable file
@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
|
||||
case $1 in
|
||||
*post-checkout)
|
||||
ACTION='Branch change'
|
||||
;;
|
||||
*post-merge)
|
||||
ACTION='Remote pull'
|
||||
;;
|
||||
*)
|
||||
ACTION="Unknown event ($1)"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "${ACTION} occurred, rebuilding editor"
|
||||
|
||||
export ATOM_ELECTRON_VERSION=$(cat package.json | rg --trim --replace "" '"electronVersion": "' | rg --replace "" '",')
|
||||
|
||||
replacement="1.100.$(date +'%Y%m%d%H%k%M')"
|
||||
filter='("version": ")[0-9\.]+(",)'
|
||||
regex="s/$filter/\1$replacement\2/"
|
||||
|
||||
sed --regexp-extended --in-place "$regex" package.json
|
||||
|
||||
echo ' Installing editor packages'
|
||||
yarn install &> /dev/null
|
||||
if [[ $? == 0 ]]; then
|
||||
echo ' Install completed successfully'
|
||||
else
|
||||
echo ' Install failed'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ' Rebuilding modules'
|
||||
yarn build &> /dev/null
|
||||
if [[ $? == 0 ]]; then
|
||||
echo ' Module build completed successfully'
|
||||
else
|
||||
echo ' Module build failed'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ' Rebuilding PPM'
|
||||
if [[ -d "ppm" ]]; then
|
||||
yarn build:apm &> /dev/null
|
||||
if [[ $? == 0 ]]; then
|
||||
echo ' PPM build completed successfully'
|
||||
else
|
||||
echo ' PPM build failed'
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo ' PPM folder not found'
|
||||
fi
|
||||
|
||||
git submodule sync && git submodule update
|
115
package.json
115
package.json
@ -2,7 +2,7 @@
|
||||
"name": "pulsar",
|
||||
"author": "Pulsar Community <noreply@pulsar-edit.com>",
|
||||
"productName": "Pulsar",
|
||||
"version": "1.63.0-dev",
|
||||
"version": "1.102.0-dev",
|
||||
"description": "A Community-led Hyper-Hackable Text Editor",
|
||||
"branding": {
|
||||
"id": "pulsar",
|
||||
@ -25,7 +25,7 @@
|
||||
"@babel/core": "7.18.6",
|
||||
"@electron/remote": "2.0.8",
|
||||
"about": "file:packages/about",
|
||||
"archive-view": "https://codeload.github.com/atom/archive-view/legacy.tar.gz/refs/tags/v0.66.0",
|
||||
"archive-view": "file:packages/archive-view",
|
||||
"async": "3.2.4",
|
||||
"atom-dark-syntax": "file:packages/atom-dark-syntax",
|
||||
"atom-dark-ui": "file:packages/atom-dark-ui",
|
||||
@ -34,32 +34,30 @@
|
||||
"atom-light-ui": "file:packages/atom-light-ui",
|
||||
"atom-select-list": "^0.8.1",
|
||||
"autocomplete-atom-api": "https://codeload.github.com/atom/autocomplete-atom-api/legacy.tar.gz/refs/tags/v0.10.7",
|
||||
"autocomplete-css": "https://codeload.github.com/atom/autocomplete-css/legacy.tar.gz/refs/tags/v0.17.5",
|
||||
"autocomplete-html": "https://github.com/pulsar-edit/autocomplete-html.git#v0.8.9",
|
||||
"autocomplete-plus": "https://codeload.github.com/atom/autocomplete-plus/legacy.tar.gz/refs/tags/v2.42.5",
|
||||
"autocomplete-snippets": "https://codeload.github.com/atom/autocomplete-snippets/legacy.tar.gz/refs/tags/v1.12.1",
|
||||
"autocomplete-css": "file:packages/autocomplete-css",
|
||||
"autocomplete-html": "file:packages/autocomplete-html",
|
||||
"autocomplete-plus": "file:./packages/autocomplete-plus",
|
||||
"autocomplete-snippets": "file:packages/autocomplete-snippets",
|
||||
"autoflow": "file:packages/autoflow",
|
||||
"autosave": "https://codeload.github.com/atom/autosave/legacy.tar.gz/refs/tags/v0.24.6",
|
||||
"babel-preset-atomic": "^5.0.0",
|
||||
"background-tips": "https://codeload.github.com/pulsar-edit/background-tips/legacy.tar.gz/refs/tags/v0.28.1",
|
||||
"background-tips": "file:packages/background-tips",
|
||||
"base16-tomorrow-dark-theme": "file:packages/base16-tomorrow-dark-theme",
|
||||
"base16-tomorrow-light-theme": "file:packages/base16-tomorrow-light-theme",
|
||||
"bookmarks": "https://codeload.github.com/atom/bookmarks/legacy.tar.gz/refs/tags/v0.46.0",
|
||||
"bracket-matcher": "https://github.com/pulsar-edit/bracket-matcher.git#use-napi-oniguruma",
|
||||
"bracket-matcher": "https://github.com/pulsar-edit/bracket-matcher.git#c877977",
|
||||
"chai": "4.3.4",
|
||||
"clear-cut": "^2.0.2",
|
||||
"coffee-script": "1.12.7",
|
||||
"coffeescript": "1.12.7",
|
||||
"color": "3.1.3",
|
||||
"command-palette": "https://codeload.github.com/atom/command-palette/legacy.tar.gz/refs/tags/v0.43.5",
|
||||
"command-palette": "file:packages/command-palette",
|
||||
"dalek": "file:packages/dalek",
|
||||
"dedent": "^0.7.0",
|
||||
"deprecation-cop": "file:packages/deprecation-cop",
|
||||
"dev-live-reload": "file:packages/dev-live-reload",
|
||||
"devtron": "1.4.0",
|
||||
"document-register-element": "^1.14.10",
|
||||
"electron-notarize": "1.0.0",
|
||||
"electron-osx-sign": "0.5.0",
|
||||
"encoding-selector": "https://codeload.github.com/atom/encoding-selector/legacy.tar.gz/refs/tags/v0.23.9",
|
||||
"encoding-selector": "file:packages/encoding-selector",
|
||||
"etch": "0.14.1",
|
||||
"event-kit": "^2.5.3",
|
||||
"exception-reporting": "file:packages/exception-reporting",
|
||||
@ -70,14 +68,14 @@
|
||||
"fs-admin": "0.19.0",
|
||||
"fs-plus": "^3.1.1",
|
||||
"fstream": "1.0.12",
|
||||
"fuzzaldrin": "^2.1",
|
||||
"fuzzy-finder": "https://github.com/pulsar-edit/fuzzy-finder.git#simplify-code",
|
||||
"git-diff": "file:packages/git-diff",
|
||||
"git-utils": "5.7.1",
|
||||
"glob": "^7.1.1",
|
||||
"go-to-line": "file:packages/go-to-line",
|
||||
"grammar-selector": "file:packages/grammar-selector",
|
||||
"grim": "2.0.3",
|
||||
"image-view": "https://codeload.github.com/atom/image-view/legacy.tar.gz/refs/tags/v0.64.0",
|
||||
"image-view": "file:packages/image-view",
|
||||
"incompatible-packages": "file:packages/incompatible-packages",
|
||||
"jasmine-json": "~0.0",
|
||||
"jasmine-reporters": "1.1.0",
|
||||
@ -122,7 +120,7 @@
|
||||
"line-ending-selector": "file:packages/line-ending-selector",
|
||||
"line-top-index": "0.3.1",
|
||||
"link": "file:packages/link",
|
||||
"markdown-preview": "https://codeload.github.com/atom/markdown-preview/legacy.tar.gz/refs/tags/v0.160.2",
|
||||
"markdown-preview": "file:./packages/markdown-preview",
|
||||
"minimatch": "^3.0.3",
|
||||
"mocha": "6.2.3",
|
||||
"mocha-junit-reporter": "2.0.0",
|
||||
@ -137,44 +135,45 @@
|
||||
"one-light-syntax": "file:packages/one-light-syntax",
|
||||
"one-light-ui": "file:packages/one-light-ui",
|
||||
"oniguruma": "https://github.com/Aerijo/napi-oniguruma.git",
|
||||
"open-on-github": "https://codeload.github.com/atom/open-on-github/legacy.tar.gz/refs/tags/v1.3.2",
|
||||
"package-generator": "https://codeload.github.com/atom/package-generator/legacy.tar.gz/refs/tags/v1.3.0",
|
||||
"package-generator": "file:packages/package-generator",
|
||||
"pathwatcher": "^8.1.2",
|
||||
"postcss": "8.2.10",
|
||||
"postcss-selector-parser": "6.0.4",
|
||||
"prebuild-install": "6.0.0",
|
||||
"property-accessors": "^1.1.3",
|
||||
"resolve": "1.18.1",
|
||||
"scandal": "^3.2.0",
|
||||
"scoped-property-store": "^0.17.0",
|
||||
"scrollbar-style": "^4.0.1",
|
||||
"season": "^6.0.2",
|
||||
"semver": "7.3.2",
|
||||
"semver": "7.3.8",
|
||||
"service-hub": "^0.7.4",
|
||||
"settings-view": "https://github.com/pulsar-edit/settings-view.git#v0.261.11",
|
||||
"settings-view": "file:packages/settings-view",
|
||||
"sinon": "9.2.1",
|
||||
"snippets": "https://codeload.github.com/pulsar-edit/snippets/legacy.tar.gz/refs/tags/v1.6.1",
|
||||
"snippets": "github:pulsar-edit/snippets#bb00f909c6c645b173f27346875d8fa0c7af09f7",
|
||||
"solarized-dark-syntax": "file:packages/solarized-dark-syntax",
|
||||
"solarized-light-syntax": "file:packages/solarized-light-syntax",
|
||||
"source-map-support": "0.5.21",
|
||||
"spell-check": "https://codeload.github.com/atom/spell-check/legacy.tar.gz/refs/tags/v0.77.1",
|
||||
"status-bar": "https://codeload.github.com/atom/status-bar/legacy.tar.gz/refs/tags/v1.8.17",
|
||||
"styleguide": "https://codeload.github.com/atom/styleguide/legacy.tar.gz/refs/tags/v0.49.12",
|
||||
"sqlite3": "4",
|
||||
"status-bar": "file:packages/status-bar",
|
||||
"styleguide": "file:./packages/styleguide",
|
||||
"superstring": "https://github.com/pulsar-edit/superstring-wasm.git#536739fef8f8cab757970b5aa56397e2f9493a02",
|
||||
"symbols-view": "https://codeload.github.com/atom/symbols-view/legacy.tar.gz/refs/tags/v0.118.4",
|
||||
"tabs": "https://codeload.github.com/atom/tabs/legacy.tar.gz/refs/tags/v0.110.2",
|
||||
"temp": "0.9.2",
|
||||
"tabs": "file:packages/tabs",
|
||||
"temp": "0.9.4",
|
||||
"text-buffer": "https://github.com/pulsar-edit/text-buffer.git#f8702c877",
|
||||
"timecop": "https://codeload.github.com/atom/timecop/legacy.tar.gz/refs/tags/v0.36.2",
|
||||
"tree-sitter": "https://github.com/pulsar-edit/node-tree-sitter.git#c304335",
|
||||
"tree-view": "https://github.com/pulsar-edit/tree-view.git#4274c7a",
|
||||
"typescript-simple": "8.0.6",
|
||||
"underscore-plus": "^1.7.0",
|
||||
"update-package-dependencies": "file:./packages/update-package-dependencies",
|
||||
"vscode-ripgrep": "1.9.0",
|
||||
"welcome": "file:packages/welcome",
|
||||
"whitespace": "https://codeload.github.com/atom/whitespace/legacy.tar.gz/refs/tags/v0.37.8",
|
||||
"winreg": "^1.2.1",
|
||||
"wrap-guide": "https://codeload.github.com/atom/wrap-guide/legacy.tar.gz/refs/tags/v0.41.0",
|
||||
"yargs": "16.1.0"
|
||||
"wrap-guide": "file:./packages/wrap-guide",
|
||||
"yargs": "17.6.2"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "file:./packages/atom-dark-syntax",
|
||||
@ -190,50 +189,50 @@
|
||||
"solarized-dark-syntax": "file:./packages/solarized-dark-syntax",
|
||||
"solarized-light-syntax": "file:./packages/solarized-light-syntax",
|
||||
"about": "file:./packages/about",
|
||||
"archive-view": "0.66.0",
|
||||
"archive-view": "file:./packages/archive-view",
|
||||
"autocomplete-atom-api": "0.10.7",
|
||||
"autocomplete-css": "0.17.5",
|
||||
"autocomplete-html": "0.8.9",
|
||||
"autocomplete-plus": "2.42.5",
|
||||
"autocomplete-snippets": "1.12.1",
|
||||
"autocomplete-css": "file:./packages/autocomplete-css",
|
||||
"autocomplete-html": "file:./packages/autocomplete-html",
|
||||
"autocomplete-plus": "file:./packages/autocomplete-plus",
|
||||
"autocomplete-snippets": "file:./packages/autocomplete-snippets",
|
||||
"autoflow": "file:./packages/autoflow",
|
||||
"autosave": "0.24.6",
|
||||
"background-tips": "0.28.0",
|
||||
"bookmarks": "0.46.0",
|
||||
"background-tips": "file:./packages/background-tips",
|
||||
"bookmarks": "file:./packages/bookmarks",
|
||||
"bracket-matcher": "0.92.0",
|
||||
"command-palette": "0.43.5",
|
||||
"command-palette": "file:./packages/command-palette",
|
||||
"dalek": "file:./packages/dalek",
|
||||
"deprecation-cop": "file:./packages/deprecation-cop",
|
||||
"dev-live-reload": "file:./packages/dev-live-reload",
|
||||
"encoding-selector": "0.23.9",
|
||||
"encoding-selector": "file:./packages/encoding-selector",
|
||||
"exception-reporting": "file:./packages/exception-reporting",
|
||||
"find-and-replace": "0.220.1",
|
||||
"fuzzy-finder": "1.14.3",
|
||||
"git-diff": "file:./packages/git-diff",
|
||||
"go-to-line": "file:./packages/go-to-line",
|
||||
"grammar-selector": "file:./packages/grammar-selector",
|
||||
"image-view": "0.64.0",
|
||||
"image-view": "file:./packages/image-view",
|
||||
"incompatible-packages": "file:./packages/incompatible-packages",
|
||||
"keybinding-resolver": "0.39.1",
|
||||
"line-ending-selector": "file:./packages/line-ending-selector",
|
||||
"link": "file:./packages/link",
|
||||
"markdown-preview": "0.160.2",
|
||||
"markdown-preview": "file:./packages/markdown-preview",
|
||||
"notifications": "0.72.1",
|
||||
"open-on-github": "1.3.2",
|
||||
"package-generator": "1.3.0",
|
||||
"settings-view": "0.261.9",
|
||||
"open-on-github": "file:./packages/open-on-github",
|
||||
"package-generator": "file:./packages/package-generator",
|
||||
"settings-view": "file:./packages/settings-view",
|
||||
"snippets": "1.6.1",
|
||||
"spell-check": "0.77.1",
|
||||
"status-bar": "1.8.17",
|
||||
"styleguide": "0.49.12",
|
||||
"status-bar": "file:./packages/status-bar",
|
||||
"styleguide": "file:./packages/styleguide",
|
||||
"symbols-view": "0.118.4",
|
||||
"tabs": "0.110.2",
|
||||
"tabs": "file:./packages/tabs",
|
||||
"timecop": "0.36.2",
|
||||
"tree-view": "0.229.1",
|
||||
"update-package-dependencies": "file:./packages/update-package-dependencies",
|
||||
"welcome": "file:./packages/welcome",
|
||||
"whitespace": "0.37.8",
|
||||
"wrap-guide": "0.41.0",
|
||||
"wrap-guide": "file:./packages/wrap-guide",
|
||||
"language-c": "file:./packages/language-c",
|
||||
"language-clojure": "file:./packages/language-clojure",
|
||||
"language-coffee-script": "file:./packages/language-coffee-script",
|
||||
@ -271,31 +270,23 @@
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "node -e 'process.exit(0)'",
|
||||
"build": "electron-rebuild",
|
||||
"build:apm": "cd ppm && yarn install",
|
||||
"start": "electron --enable-logging . -f",
|
||||
"dist": "node script/electron-builder.js"
|
||||
},
|
||||
"standard-engine": "./script/node_modules/standard",
|
||||
"standard": {
|
||||
"env": {
|
||||
"atomtest": true,
|
||||
"browser": true,
|
||||
"jasmine": true,
|
||||
"node": true
|
||||
},
|
||||
"globals": [
|
||||
"atom"
|
||||
]
|
||||
"start": "electron --no-sandbox --enable-logging . -f",
|
||||
"dist": "node script/electron-builder.js",
|
||||
"js-docs": "jsdoc2md --files src --configure docs/.jsdoc.json > ./docs/Pulsar-API-Documentation.md",
|
||||
"private-js-docs": "jsdoc2md --private --files src --configure docs/.jsdoc.json > ./docs/Source-Code-Documentation.md"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron/notarize": "^1.2.3",
|
||||
"@playwright/test": "1.22.2",
|
||||
"electron": "12.2.3",
|
||||
"electron-builder": "23.3.1",
|
||||
"electron-rebuild": "3.2.7",
|
||||
"eslint": "^8.27.0",
|
||||
"eslint": "^8.33.0",
|
||||
"eslint-plugin-jsdoc": "^39.7.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"jsdoc-to-markdown": "^8.0.0",
|
||||
"playwright": "1.22.2",
|
||||
"playwright-core": "1.22.2",
|
||||
"random-seed": "0.3.0",
|
||||
|
@ -3,7 +3,7 @@
|
||||
This folder contains core packages that are bundled with Pulsar releases. Not all core packages are kept here; please
|
||||
see the table below for the location of every core package.
|
||||
|
||||
> **NOTE:** There is an ongoing effort to migrate more Atom packages from their individual repositories to this folder.
|
||||
> **NOTE:** There is an ongoing effort to migrate more Pulsar packages from their individual repositories to this folder.
|
||||
See [RFC 003](https://github.com/atom/atom/blob/master/docs/rfcs/003-consolidate-core-packages.md) for more details.
|
||||
|
||||
| Package | Where to find it | Migration issue |
|
||||
@ -14,30 +14,30 @@ See [RFC 003](https://github.com/atom/atom/blob/master/docs/rfcs/003-consolidate
|
||||
| **atom-light-syntax** | [`./atom-light-syntax`](./atom-light-syntax) | |
|
||||
| **atom-light-ui** | [`./atom-light-ui`](./atom-light-ui) | |
|
||||
| **autocomplete-atom-api** | [`atom/autocomplete-atom-api`][autocomplete-atom-api] | |
|
||||
| **autocomplete-css** | [`atom/autocomplete-css`][autocomplete-css] | |
|
||||
| **autocomplete-html** | [`atom/autocomplete-html`][autocomplete-html] | |
|
||||
| **autocomplete-plus** | [`atom/autocomplete-plus`][autocomplete-plus] | |
|
||||
| **autocomplete-snippets** | [`atom/autocomplete-snippets`][autocomplete-snippets] | |
|
||||
| **autocomplete-css** | [`./autocomplete-css`](./autocomplete-css) | |
|
||||
| **autocomplete-html** | [`./autocomplete-html`](./autocomplete-html) | |
|
||||
| **autocomplete-plus** | [`./autocomplete-plus`][./autocomplete-plus] | |
|
||||
| **autocomplete-snippets** | [`./autocomplete-snippets`](./autocomplete-snippets) | |
|
||||
| **autoflow** | [`./autoflow`](./autoflow) | |
|
||||
| **autosave** | [`atom/autosave`][autosave] | [#17834](https://github.com/atom/atom/issues/17834) |
|
||||
| **background-tips** | [`atom/background-tips`][background-tips] | [#17835](https://github.com/atom/atom/issues/17835) |
|
||||
| **autosave** | [`pulsar-edit/autosave`][autosave] | [#17834](https://github.com/atom/atom/issues/17834) |
|
||||
| **background-tips** | [`./background-tips`](./background-tips) | |
|
||||
| **base16-tomorrow-dark-theme** | [`./base16-tomorrow-dark-theme`](./base16-tomorrow-dark-theme) | |
|
||||
| **base16-tomorrow-light-theme** | [`./base16-tomorrow-light-theme`](./base16-tomorrow-light-theme) | |
|
||||
| **bookmarks** | [`atom/bookmarks`][bookmarks] | [#18273](https://github.com/atom/atom/issues/18273) |
|
||||
| **bookmarks** | [`./bookmarks`](./bookmarks) | |
|
||||
| **bracket-matcher** | [`atom/bracket-matcher`][bracket-matcher] | |
|
||||
| **command-palette** | [`atom/command-palette`][command-palette] | |
|
||||
| **dalek** | [`./dalek`](./dalek) | [#17838](https://github.com/atom/atom/issues/17838) |
|
||||
| **command-palette** | [`./command-palette`](./command-palette) | |
|
||||
| **dalek** | [`./dalek`](./dalek) | |
|
||||
| **deprecation-cop** | [`./deprecation-cop`](./deprecation-cop) | |
|
||||
| **dev-live-reload** | [`./dev-live-reload`](./dev-live-reload) | |
|
||||
| **encoding-selector** | [`atom/encoding-selector`][encoding-selector] | [#17841](https://github.com/atom/atom/issues/17841) |
|
||||
| **encoding-selector** | [`./encoding-selector`](./encoding-selector) | |
|
||||
| **exception-reporting** | [`./exception-reporting`](./exception-reporting) | |
|
||||
| **find-and-replace** | [`atom/find-and-replace`][find-and-replace] | |
|
||||
| **fuzzy-finder** | [`atom/fuzzy-finder`][fuzzy-finder] | |
|
||||
| **github** | [`atom/github`][github] | |
|
||||
| **find-and-replace** | [`pulsar-edit/find-and-replace`][find-and-replace] | |
|
||||
| **fuzzy-finder** | [`pulsar-edit/fuzzy-finder`][fuzzy-finder] | |
|
||||
| **github** | [`pulsar-edit/github`][github] | |
|
||||
| **git-diff** | [`./git-diff`](./git-diff) | |
|
||||
| **go-to-line** | [`./go-to-line`](./go-to-line) | |
|
||||
| **grammar-selector** | [`./grammar-selector`](./grammar-selector) | |
|
||||
| **image-view** | [`atom/image-view`][image-view] | [#18274](https://github.com/atom/atom/issues/18274) |
|
||||
| **image-view** | [`./image-view`](./image-view) | |
|
||||
| **incompatible-packages** | [`./incompatible-packages`](./incompatible-packages) | |
|
||||
| **keybinding-resolver** | [`atom/keybinding-resolver`][keybinding-resolver] | [#18275](https://github.com/atom/atom/issues/18275) |
|
||||
| **language-c** | [`./language-c`](./language-c) | |
|
||||
@ -76,59 +76,40 @@ See [RFC 003](https://github.com/atom/atom/blob/master/docs/rfcs/003-consolidate
|
||||
| **language-yaml** | [`./language-yaml`](./language-yaml) | |
|
||||
| **line-ending-selector** | [`./line-ending-selector`](./line-ending-selector) | |
|
||||
| **link** | [`./link`](./link) | |
|
||||
| **markdown-preview** | [`atom/markdown-preview`][markdown-preview] | |
|
||||
| **markdown-preview** | [`./markdown-preview`][./markdown-preview] | |
|
||||
| **notifications** | [`atom/notifications`][notifications] | [#18277](https://github.com/atom/atom/issues/18277) |
|
||||
| **one-dark-syntax** | [`./one-dark-syntax`](./one-dark-syntax) | |
|
||||
| **one-dark-ui** | [`./one-dark-ui`](./one-dark-ui) | |
|
||||
| **one-light-syntax** | [`./one-light-syntax`](./one-light-syntax) | |
|
||||
| **one-light-ui** | [`./one-light-ui`](./one-light-ui) | |
|
||||
| **open-on-github** | [`atom/open-on-github`][open-on-github] | [#18278](https://github.com/atom/atom/issues/18278) |
|
||||
| **package-generator** | [`atom/package-generator`][package-generator] | [#18279](https://github.com/atom/atom/issues/18279) |
|
||||
| **settings-view** | [`atom/settings-view`][settings-view] | |
|
||||
| **snippets** | [`atom/snippets`][snippets] | |
|
||||
| **open-on-github** | [`./open-on-github`](./open-on-github) | |
|
||||
| **settings-view** | [`./settings-view`](./settings-view) | |
|
||||
| **package-generator** | [`./package-generator`](./package-generator) | |
|
||||
| **snippets** | [`pulsar-edit/snippets`][snippets] | |
|
||||
| **solarized-dark-syntax** | [`./solarized-dark-syntax`](./solarized-dark-syntax) | |
|
||||
| **solarized-light-syntax** | [`./solarized-light-syntax`](./solarized-light-syntax) | |
|
||||
| **spell-check** | [`atom/spell-check`][spell-check] | |
|
||||
| **status-bar** | [`atom/status-bar`][status-bar] | [#18282](https://github.com/atom/atom/issues/18282) |
|
||||
| **styleguide** | [`atom/styleguide`][styleguide] | [#18283](https://github.com/atom/atom/issues/18283) |
|
||||
| **symbols-view** | [`atom/symbols-view`][symbols-view] | |
|
||||
| **tabs** | [`atom/tabs`][tabs] | |
|
||||
| **timecop** | [`atom/timecop`][timecop] | [#18272](https://github.com/atom/atom/issues/18272) |
|
||||
| **tree-view** | [`atom/tree-view`][tree-view] | |
|
||||
| **status-bar** | [`./status-bar`](./status-bar) | |
|
||||
| **styleguide** | [`./styleguide`][./styleguide] | |
|
||||
| **symbols-view** | [`pulsar-edit/symbols-view`][symbols-view] | |
|
||||
| **tabs** | [`./tabs`](./tabs) | |
|
||||
| **timecop** | [`pulsar-edit/timecop`][timecop] | [#18272](https://github.com/atom/atom/issues/18272) |
|
||||
| **tree-view** | [`pulsar-edit/tree-view`][tree-view] | |
|
||||
| **update-package-dependencies** | [`./update-package-dependencies`](./update-package-dependencies) | |
|
||||
| **welcome** | [`./welcome`](./welcome) | |
|
||||
| **whitespace** | [`atom/whitespace`][whitespace] | |
|
||||
| **wrap-guide** | [`atom/wrap-guide`][wrap-guide] | [#18286](https://github.com/atom/atom/issues/18286) |
|
||||
| **whitespace** | [`./whitespace`](./whitespace) | |
|
||||
| **wrap-guide** | [`./wrap-guide`][./wrap-guide] | |
|
||||
|
||||
[archive-view]: https://github.com/pulsar-edit/archive-view
|
||||
[autocomplete-atom-api]: https://github.com/pulsar-edit/autocomplete-atom-api
|
||||
[autocomplete-css]: https://github.com/pulsar-edit/autocomplete-css
|
||||
[autocomplete-html]: https://github.com/pulsar-edit/autocomplete-html
|
||||
[autocomplete-plus]: https://github.com/pulsar-edit/autocomplete-plus
|
||||
[autocomplete-snippets]: https://github.com/pulsar-edit/autocomplete-snippets
|
||||
[autosave]: https://github.com/pulsar-edit/autosave
|
||||
[background-tips]: https://github.com/pulsar-edit/background-tips
|
||||
[bookmarks]: https://github.com/pulsar-edit/bookmarks
|
||||
[bracket-matcher]: https://github.com/pulsar-edit/bracket-matcher
|
||||
[command-palette]: https://github.com/pulsar-edit/command-palette
|
||||
[encoding-selector]: https://github.com/pulsar-edit/encoding-selector
|
||||
[find-and-replace]: https://github.com/pulsar-edit/find-and-replace
|
||||
[fuzzy-finder]: https://github.com/pulsar-edit/fuzzy-finder
|
||||
[github]: https://github.com/pulsar-edit/github
|
||||
[image-view]: https://github.com/pulsar-edit/image-view
|
||||
[keybinding-resolver]: https://github.com/pulsar-edit/keybinding-resolver
|
||||
[markdown-preview]: https://github.com/pulsar-edit/markdown-preview
|
||||
[notifications]: https://github.com/pulsar-edit/notifications
|
||||
[open-on-github]: https://github.com/pulsar-edit/open-on-github
|
||||
[package-generator]: https://github.com/pulsar-edit/package-generator
|
||||
[settings-view]: https://github.com/pulsar-edit/settings-view
|
||||
[snippets]: https://github.com/pulsar-edit/snippets
|
||||
[spell-check]: https://github.com/pulsar-edit/spell-check
|
||||
[status-bar]: https://github.com/pulsar-edit/status-bar
|
||||
[styleguide]: https://github.com/pulsar-edit/styleguide
|
||||
[symbols-view]: https://github.com/pulsar-edit/symbols-view
|
||||
[tabs]: https://github.com/pulsar-edit/tabs
|
||||
[timecop]: https://github.com/pulsar-edit/timecop
|
||||
[tree-view]: https://github.com/pulsar-edit/tree-view
|
||||
[whitespace]: https://github.com/pulsar-edit/whitespace
|
||||
[wrap-guide]: https://github.com/pulsar-edit/wrap-guide
|
||||
|
@ -1,20 +1,22 @@
|
||||
Copyright (c) 2015 Machisté N. Quintana
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
Copyright (c) 2022 Pulsar-Edit
|
||||
Original work copyright (c) 2015 Machisté N. Quintana
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
@ -1,21 +1,17 @@
|
||||
# About package
|
||||
|
||||
View useful information about your Atom installation.
|
||||
View useful information about your Pulsar installation.
|
||||
|
||||
![About Atom](https://cloud.githubusercontent.com/assets/16760489/19395499/69bbb780-922d-11e6-9779-2b8327027ea5.png)
|
||||
![About Pulsar](https://cloud.githubusercontent.com/assets/16760489/19395499/69bbb780-922d-11e6-9779-2b8327027ea5.png)
|
||||
|
||||
This is a package for [Atom](https://atom.io), a community-led hyper-hackable text editor
|
||||
This is a package for [Pulsar](https://pulsar-edit.dev), a community-led hyper-hackable text editor
|
||||
|
||||
## Usage
|
||||
|
||||
This package provides a cross-platform "About Atom" view that displays information about your Atom installation, which currently includes the current version, the license, and the Terms of Use.
|
||||
This package provides a cross-platform "About Pulsar" view that displays information about your Pulsar installation, which currently includes the current version, the license, and the Terms of Use.
|
||||
|
||||
## Contributing
|
||||
Always feel free to help out! Whether it's filing bugs and feature requests
|
||||
or working on some of the open issues, Atom's [contributing guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md)
|
||||
will help get you started while the [guide for contributing to packages](https://github.com/atom/atom/blob/master/docs/contributing-to-packages.md)
|
||||
or working on some of the open issues, Pulsar's [contributing guide](https://github.com/pulsar-edit/.github/blob/main/CONTRIBUTING.md)
|
||||
will help get you started while the [guide for contributing to packages](https://pulsar-edit.dev/docs/launch-manual/sections/core-hacking/#contributing-to-packages)
|
||||
has some extra information.
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](https://opensource.org/licenses/MIT) - see the [LICENSE](https://github.com/atom/about/blob/master/LICENSE.md) for more details.
|
||||
|
@ -1,7 +1,7 @@
|
||||
const { Disposable } = require('atom');
|
||||
const etch = require('etch');
|
||||
const { shell } = require('electron');
|
||||
const AtomLogo = require('./atom-logo'); //Update to new Pulsar logo (L#83)
|
||||
const AtomLogo = require('./atom-logo');
|
||||
const EtchComponent = require('../etch-component');
|
||||
const UpdateView = require('./update-view');
|
||||
|
||||
@ -46,6 +46,7 @@ module.exports = class AboutView extends EtchComponent {
|
||||
handleTermsOfUseClick(e) {
|
||||
e.preventDefault();
|
||||
shell.openExternal('https://atom.io/terms'); //If we use this then this URL will need updating but button disabled (L#182)
|
||||
// TODO Update to Privacy Policy once `pulsar-edit.github.io` #161 is resolved
|
||||
}
|
||||
|
||||
handleHowToUpdateClick(e) {
|
||||
@ -80,8 +81,7 @@ module.exports = class AboutView extends EtchComponent {
|
||||
{ className: 'about-header' },
|
||||
$.a(
|
||||
{ className: 'about-atom-io', href: `${atom.branding.urlWeb}`, },
|
||||
//$(AtomLogo)
|
||||
'Pulsar' //Remove and reinstate above line when available
|
||||
$(AtomLogo)
|
||||
),
|
||||
$.div(
|
||||
{ className: 'about-header-info' },
|
||||
@ -224,4 +224,3 @@ module.exports = class AboutView extends EtchComponent {
|
||||
return 'info';
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -125,7 +125,7 @@ let UpdateManager = class UpdateManager {
|
||||
getReleaseNotesURLForVersion(appVersion) {
|
||||
// Dev versions will not have a releases page
|
||||
if (appVersion.indexOf('dev') > -1) {
|
||||
return 'https://atom.io/releases';
|
||||
return 'https://pulsar-edit.dev/download.html';
|
||||
}
|
||||
|
||||
if (!appVersion.startsWith('v')) {
|
||||
|
1821
packages/about/package-lock.json
generated
1821
packages/about/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -10,8 +10,8 @@
|
||||
"atom": ">=1.7 <2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"etch": "0.9.0",
|
||||
"semver": "^5.5.0"
|
||||
"etch": "^0.14.1",
|
||||
"semver": "^7.3.8"
|
||||
},
|
||||
"consumedServices": {
|
||||
"status-bar": {
|
||||
|
@ -25,7 +25,7 @@ describe('About', () => {
|
||||
});
|
||||
|
||||
describe('when the about:about-atom command is triggered', () => {
|
||||
it('shows the About Atom view', async () => {
|
||||
it('shows the About Pulsar view', async () => {
|
||||
// Attaching the workspaceElement to the DOM is required to allow the
|
||||
// `toBeVisible()` matchers to work. Anything testing visibility or focus
|
||||
// requires that the workspaceElement is on the DOM. Tests that attach the
|
||||
@ -40,7 +40,7 @@ describe('About', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the Atom version number is clicked', () => {
|
||||
describe('when the Pulsar version number is clicked', () => {
|
||||
it('copies the version number to the clipboard', async () => {
|
||||
await atom.workspace.open('atom://about');
|
||||
jasmine.attachToDOM(workspaceElement);
|
||||
|
@ -60,7 +60,7 @@ describe('the status bar', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('continues to show the squirrel until Atom is updated to the new version', async () => {
|
||||
it('continues to show the squirrel until Pulsar is updated to the new version', async () => {
|
||||
MockUpdater.finishDownloadingUpdate('42.0.0');
|
||||
expect(workspaceElement).toContain('.about-release-notes');
|
||||
|
||||
@ -81,7 +81,7 @@ describe('the status bar', () => {
|
||||
expect(workspaceElement).not.toContain('.about-release-notes');
|
||||
});
|
||||
|
||||
it('does not show the view if Atom is updated to a newer version than notified', async () => {
|
||||
it('does not show the view if Pulsar is updated to a newer version than notified', async () => {
|
||||
MockUpdater.finishDownloadingUpdate('42.0.0');
|
||||
|
||||
await atom.packages.deactivatePackage('about');
|
||||
@ -125,7 +125,7 @@ describe('the status bar', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('continues to show the squirrel until Atom is updated to the new version', async () => {
|
||||
it('continues to show the squirrel until Pulsar is updated to the new version', async () => {
|
||||
MockUpdater.finishDownloadingUpdate('42.0.0');
|
||||
expect(workspaceElement).toContain('.about-release-notes');
|
||||
|
||||
@ -146,7 +146,7 @@ describe('the status bar', () => {
|
||||
expect(workspaceElement).not.toContain('.about-release-notes');
|
||||
});
|
||||
|
||||
it('does not show the view if Atom is updated to a newer version than notified', async () => {
|
||||
it('does not show the view if Pulsar is updated to a newer version than notified', async () => {
|
||||
MockUpdater.finishDownloadingUpdate('42.0.0');
|
||||
|
||||
await atom.packages.deactivatePackage('about');
|
||||
|
@ -8,26 +8,27 @@ describe('UpdateManager', () => {
|
||||
});
|
||||
|
||||
describe('::getReleaseNotesURLForVersion', () => {
|
||||
it('returns atom.io releases when dev version', () => {
|
||||
it('returns pulsar-edit download page when dev version', () => {
|
||||
expect(
|
||||
updateManager.getReleaseNotesURLForVersion('1.7.0-dev-e44b57d')
|
||||
).toContain('atom.io/releases');
|
||||
).toContain('pulsar-edit.dev/download');
|
||||
});
|
||||
|
||||
it('returns the page for the release when not a dev version', () => {
|
||||
expect(updateManager.getReleaseNotesURLForVersion('1.7.0')).toContain(
|
||||
'atom-ide-community/atom/releases/tag/v1.7.0'
|
||||
expect(updateManager.getReleaseNotesURLForVersion('1.100.0')).toContain(
|
||||
'pulsar-edit/pulsar/releases/tag/v1.100.0'
|
||||
);
|
||||
expect(updateManager.getReleaseNotesURLForVersion('v1.7.0')).toContain(
|
||||
'atom-ide-community/atom/releases/tag/v1.7.0'
|
||||
expect(updateManager.getReleaseNotesURLForVersion('v1.100.0')).toContain(
|
||||
'pulsar-edit/pulsar/releases/tag/v1.100.0'
|
||||
);
|
||||
// TODO: Since we no longer follow release channels, is it useful to continue testing their state?
|
||||
expect(
|
||||
updateManager.getReleaseNotesURLForVersion('1.7.0-beta10')
|
||||
).toContain('atom-ide-community/atom/releases/tag/v1.7.0-beta10');
|
||||
updateManager.getReleaseNotesURLForVersion('1.100.0-beta10')
|
||||
).toContain('pulsar-edit/pulsar/releases/tag/v1.100.0-beta10');
|
||||
expect(
|
||||
updateManager.getReleaseNotesURLForVersion('1.7.0-nightly10')
|
||||
updateManager.getReleaseNotesURLForVersion('1.100.0-nightly10')
|
||||
).toContain(
|
||||
'atom-ide-community/atom-nightly-releases/releases/tag/v1.7.0-nightly10'
|
||||
'pulsar-edit/pulsar-nightly-releases/releases/tag/v1.100.0-nightly10'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -61,7 +61,7 @@ describe('UpdateView', () => {
|
||||
|
||||
let args = shell.openExternal.mostRecentCall.args;
|
||||
expect(shell.openExternal).toHaveBeenCalled();
|
||||
expect(args[0]).toContain('installing-atom');
|
||||
expect(args[0]).toContain('installing-pulsar');
|
||||
});
|
||||
});
|
||||
|
||||
@ -241,120 +241,120 @@ describe('UpdateView', () => {
|
||||
).toBe('Check now');
|
||||
});
|
||||
|
||||
describe('when core.automaticallyUpdate is toggled', () => {
|
||||
beforeEach(async () => {
|
||||
expect(atom.config.get('core.automaticallyUpdate')).toBe(true);
|
||||
atom.autoUpdater.checkForUpdate.reset();
|
||||
});
|
||||
|
||||
it('shows the auto update UI', async () => {
|
||||
expect(
|
||||
aboutElement.querySelector('.about-auto-updates input').checked
|
||||
).toBe(true);
|
||||
expect(
|
||||
aboutElement.querySelector('.about-default-update-message')
|
||||
).toBeVisible();
|
||||
expect(
|
||||
aboutElement.querySelector('.about-default-update-message')
|
||||
.textContent
|
||||
).toBe('Pulsar will check for updates automatically');
|
||||
|
||||
atom.config.set('core.automaticallyUpdate', false);
|
||||
await scheduler.getNextUpdatePromise();
|
||||
|
||||
expect(
|
||||
aboutElement.querySelector('.about-auto-updates input').checked
|
||||
).toBe(false);
|
||||
expect(
|
||||
aboutElement.querySelector('.about-default-update-message')
|
||||
).toBeVisible();
|
||||
expect(
|
||||
aboutElement.querySelector('.about-default-update-message')
|
||||
.textContent
|
||||
).toBe('Automatic updates are disabled please check manually');
|
||||
});
|
||||
|
||||
it('updates config and the UI when the checkbox is used to toggle', async () => {
|
||||
expect(
|
||||
aboutElement.querySelector('.about-auto-updates input').checked
|
||||
).toBe(true);
|
||||
|
||||
aboutElement.querySelector('.about-auto-updates input').click();
|
||||
await scheduler.getNextUpdatePromise();
|
||||
|
||||
expect(atom.config.get('core.automaticallyUpdate')).toBe(false);
|
||||
expect(
|
||||
aboutElement.querySelector('.about-auto-updates input').checked
|
||||
).toBe(false);
|
||||
expect(
|
||||
aboutElement.querySelector('.about-default-update-message')
|
||||
).toBeVisible();
|
||||
expect(
|
||||
aboutElement.querySelector('.about-default-update-message')
|
||||
.textContent
|
||||
).toBe('Automatic updates are disabled please check manually');
|
||||
|
||||
aboutElement.querySelector('.about-auto-updates input').click();
|
||||
await scheduler.getNextUpdatePromise();
|
||||
|
||||
expect(atom.config.get('core.automaticallyUpdate')).toBe(true);
|
||||
expect(
|
||||
aboutElement.querySelector('.about-auto-updates input').checked
|
||||
).toBe(true);
|
||||
expect(
|
||||
aboutElement.querySelector('.about-default-update-message')
|
||||
).toBeVisible();
|
||||
expect(
|
||||
aboutElement.querySelector('.about-default-update-message')
|
||||
.textContent
|
||||
).toBe('Pulsar will check for updates automatically');
|
||||
});
|
||||
|
||||
describe('checking for updates', function() {
|
||||
afterEach(() => {
|
||||
this.updateView = null;
|
||||
});
|
||||
|
||||
it('checks for update when the about page is shown', () => {
|
||||
expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled();
|
||||
|
||||
this.updateView = new UpdateView({
|
||||
updateManager: updateManager,
|
||||
availableVersion: '9999.0.0',
|
||||
viewUpdateReleaseNotes: () => {}
|
||||
});
|
||||
|
||||
expect(atom.autoUpdater.checkForUpdate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not check for update when the about page is shown and the update manager is not in the idle state', () => {
|
||||
atom.autoUpdater.getState.andReturn('downloading');
|
||||
updateManager.resetState();
|
||||
expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled();
|
||||
|
||||
this.updateView = new UpdateView({
|
||||
updateManager: updateManager,
|
||||
availableVersion: '9999.0.0',
|
||||
viewUpdateReleaseNotes: () => {}
|
||||
});
|
||||
|
||||
expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not check for update when the about page is shown and auto updates are turned off', () => {
|
||||
atom.config.set('core.automaticallyUpdate', false);
|
||||
expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled();
|
||||
|
||||
this.updateView = new UpdateView({
|
||||
updateManager: updateManager,
|
||||
availableVersion: '9999.0.0',
|
||||
viewUpdateReleaseNotes: () => {}
|
||||
});
|
||||
|
||||
expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
// describe('when core.automaticallyUpdate is toggled', () => {
|
||||
// beforeEach(async () => {
|
||||
// expect(atom.config.get('core.automaticallyUpdate')).toBe(true);
|
||||
// atom.autoUpdater.checkForUpdate.reset();
|
||||
// });
|
||||
//
|
||||
// it('shows the auto update UI', async () => {
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-auto-updates input').checked
|
||||
// ).toBe(true);
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-default-update-message')
|
||||
// ).toBeVisible();
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-default-update-message')
|
||||
// .textContent
|
||||
// ).toBe('Pulsar will check for updates automatically');
|
||||
//
|
||||
// atom.config.set('core.automaticallyUpdate', false);
|
||||
// await scheduler.getNextUpdatePromise();
|
||||
//
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-auto-updates input').checked
|
||||
// ).toBe(false);
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-default-update-message')
|
||||
// ).toBeVisible();
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-default-update-message')
|
||||
// .textContent
|
||||
// ).toBe('Automatic updates are disabled please check manually');
|
||||
// });
|
||||
//
|
||||
// it('updates config and the UI when the checkbox is used to toggle', async () => {
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-auto-updates input').checked
|
||||
// ).toBe(true);
|
||||
//
|
||||
// aboutElement.querySelector('.about-auto-updates input').click();
|
||||
// await scheduler.getNextUpdatePromise();
|
||||
//
|
||||
// expect(atom.config.get('core.automaticallyUpdate')).toBe(false);
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-auto-updates input').checked
|
||||
// ).toBe(false);
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-default-update-message')
|
||||
// ).toBeVisible();
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-default-update-message')
|
||||
// .textContent
|
||||
// ).toBe('Automatic updates are disabled please check manually');
|
||||
//
|
||||
// aboutElement.querySelector('.about-auto-updates input').click();
|
||||
// await scheduler.getNextUpdatePromise();
|
||||
//
|
||||
// expect(atom.config.get('core.automaticallyUpdate')).toBe(true);
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-auto-updates input').checked
|
||||
// ).toBe(true);
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-default-update-message')
|
||||
// ).toBeVisible();
|
||||
// expect(
|
||||
// aboutElement.querySelector('.about-default-update-message')
|
||||
// .textContent
|
||||
// ).toBe('Pulsar will check for updates automatically');
|
||||
// });
|
||||
//
|
||||
// describe('checking for updates', function() {
|
||||
// afterEach(() => {
|
||||
// this.updateView = null;
|
||||
// });
|
||||
//
|
||||
// it('checks for update when the about page is shown', () => {
|
||||
// expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled();
|
||||
//
|
||||
// this.updateView = new UpdateView({
|
||||
// updateManager: updateManager,
|
||||
// availableVersion: '9999.0.0',
|
||||
// viewUpdateReleaseNotes: () => {}
|
||||
// });
|
||||
//
|
||||
// expect(atom.autoUpdater.checkForUpdate).toHaveBeenCalled();
|
||||
// });
|
||||
//
|
||||
// it('does not check for update when the about page is shown and the update manager is not in the idle state', () => {
|
||||
// atom.autoUpdater.getState.andReturn('downloading');
|
||||
// updateManager.resetState();
|
||||
// expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled();
|
||||
//
|
||||
// this.updateView = new UpdateView({
|
||||
// updateManager: updateManager,
|
||||
// availableVersion: '9999.0.0',
|
||||
// viewUpdateReleaseNotes: () => {}
|
||||
// });
|
||||
//
|
||||
// expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled();
|
||||
// });
|
||||
//
|
||||
// it('does not check for update when the about page is shown and auto updates are turned off', () => {
|
||||
// atom.config.set('core.automaticallyUpdate', false);
|
||||
// expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled();
|
||||
//
|
||||
// this.updateView = new UpdateView({
|
||||
// updateManager: updateManager,
|
||||
// availableVersion: '9999.0.0',
|
||||
// viewUpdateReleaseNotes: () => {}
|
||||
// });
|
||||
//
|
||||
// expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
});
|
||||
});
|
||||
|
||||
|
20
packages/archive-view/README.md
Normal file
20
packages/archive-view/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Archive view package
|
||||
|
||||
Adds support for browsing archive files in Pulsar with the following extensions:
|
||||
|
||||
* `.egg`
|
||||
* `.epub`
|
||||
* `.jar`
|
||||
* `.love`
|
||||
* `.nupkg`
|
||||
* `.tar`
|
||||
* `.tar.gz`
|
||||
* `.tgz`
|
||||
* `.war`
|
||||
* `.whl`
|
||||
* `.xpi`
|
||||
* `.zip`
|
||||
|
||||
Select a file to extract it to a temp file and open it in a new editor.
|
||||
|
||||
![](./resources/preview.png)
|
3
packages/archive-view/keymaps/archive-view.cson
Normal file
3
packages/archive-view/keymaps/archive-view.cson
Normal file
@ -0,0 +1,3 @@
|
||||
'.archive-editor':
|
||||
'k': 'core:move-up'
|
||||
'j': 'core:move-down'
|
208
packages/archive-view/lib/archive-editor-view.js
Normal file
208
packages/archive-view/lib/archive-editor-view.js
Normal file
@ -0,0 +1,208 @@
|
||||
/** @babel */
|
||||
/** @jsx etch.dom */
|
||||
|
||||
import fs from 'fs'
|
||||
import humanize from 'humanize-plus'
|
||||
import archive from 'ls-archive'
|
||||
import {CompositeDisposable, Disposable, Emitter, File} from 'atom'
|
||||
import etch from 'etch'
|
||||
|
||||
import FileView from './file-view'
|
||||
import DirectoryView from './directory-view'
|
||||
|
||||
export default class ArchiveEditorView {
|
||||
constructor (archivePath) {
|
||||
this.disposables = new CompositeDisposable()
|
||||
this.emitter = new Emitter()
|
||||
this.path = archivePath
|
||||
this.file = new File(this.path)
|
||||
this.entries = []
|
||||
etch.initialize(this)
|
||||
|
||||
this.refresh()
|
||||
|
||||
this.disposables.add(this.file.onDidChange(() => this.refresh()))
|
||||
this.disposables.add(this.file.onDidRename(() => this.refresh()))
|
||||
this.disposables.add(this.file.onDidDelete(() => this.destroy()))
|
||||
|
||||
const focusHandler = () => this.focusSelectedFile()
|
||||
|
||||
this.element.addEventListener('focus', focusHandler)
|
||||
this.disposables.add(new Disposable(() => this.element.removeEventListener('focus', focusHandler)))
|
||||
}
|
||||
|
||||
update () {}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div className='archive-editor' tabIndex='-1'>
|
||||
<div className='archive-container'>
|
||||
<div ref='loadingMessage' className='padded icon icon-hourglass text-info'>{`Loading archive\u2026`}</div>
|
||||
<div ref='errorMessage' className='padded icon icon-alert text-error' />
|
||||
<div className='inset-panel'>
|
||||
<div ref='summary' className='panel-heading' />
|
||||
<ol ref='tree' className='archive-tree padded list-tree has-collapsable-children' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
copy () {
|
||||
return new ArchiveEditorView(this.path)
|
||||
}
|
||||
|
||||
destroy () {
|
||||
while (this.entries.length > 0) {
|
||||
this.entries.pop().destroy()
|
||||
}
|
||||
this.disposables.dispose()
|
||||
this.emitter.emit('did-destroy')
|
||||
etch.destroy(this)
|
||||
}
|
||||
|
||||
onDidDestroy (callback) {
|
||||
return this.emitter.on('did-destroy', callback)
|
||||
}
|
||||
|
||||
onDidChangeTitle (callback) {
|
||||
return this.emitter.on('did-change-title', callback)
|
||||
}
|
||||
|
||||
serialize () {
|
||||
return {
|
||||
deserializer: this.constructor.name,
|
||||
path: this.path
|
||||
}
|
||||
}
|
||||
|
||||
getPath () {
|
||||
return this.file.getPath()
|
||||
}
|
||||
|
||||
getTitle () {
|
||||
return this.path ? this.file.getBaseName() : 'untitled'
|
||||
}
|
||||
|
||||
getURI () {
|
||||
return this.path
|
||||
}
|
||||
|
||||
refresh () {
|
||||
this.refs.summary.style.display = 'none'
|
||||
this.refs.tree.style.display = 'none'
|
||||
this.refs.loadingMessage.style.display = ''
|
||||
this.refs.errorMessage.style.display = 'none'
|
||||
|
||||
if (this.path !== this.getPath()) {
|
||||
this.path = this.getPath()
|
||||
this.emitter.emit('did-change-title')
|
||||
}
|
||||
|
||||
const originalPath = this.path
|
||||
archive.list(this.path, {tree: true}, (error, entries) => {
|
||||
if (originalPath !== this.path) {
|
||||
return
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
let message = 'Reading the archive file failed'
|
||||
if (error.message) {
|
||||
message += `: ${error.message}`
|
||||
}
|
||||
this.refs.errorMessage.style.display = ''
|
||||
this.refs.errorMessage.textContent = message
|
||||
} else {
|
||||
this.createTreeEntries(entries)
|
||||
this.updateSummary()
|
||||
}
|
||||
|
||||
// We hide the loading message _after_ creating the archive tree
|
||||
// to avoid forced reflows.
|
||||
this.refs.loadingMessage.style.display = 'none'
|
||||
})
|
||||
}
|
||||
|
||||
createTreeEntries (entries) {
|
||||
while (this.entries.length > 0) {
|
||||
this.entries.pop().destroy()
|
||||
}
|
||||
|
||||
let index = 0
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
const entryView = new DirectoryView(this, index, this.path, entry)
|
||||
this.entries.push(entryView)
|
||||
} else {
|
||||
const entryView = new FileView(this, index, this.path, entry)
|
||||
this.entries.push(entryView)
|
||||
}
|
||||
index++
|
||||
}
|
||||
|
||||
this.selectFileAfterIndex(-1)
|
||||
|
||||
// Wait until selecting (focusing) the first file before appending the entries
|
||||
// to avoid a double-forced reflow when focusing.
|
||||
for (const entry of this.entries) {
|
||||
this.refs.tree.appendChild(entry.element)
|
||||
}
|
||||
|
||||
this.refs.tree.style.display = ''
|
||||
}
|
||||
|
||||
updateSummary () {
|
||||
const fileCount = this.entries.filter((entry) => entry instanceof FileView).length
|
||||
const fileLabel = fileCount === 1 ? '1 file' : `${humanize.intComma(fileCount)} files`
|
||||
|
||||
const directoryCount = this.entries.filter((entry) => entry instanceof DirectoryView).length
|
||||
const directoryLabel = directoryCount === 1 ? '1 folder' : `${humanize.intComma(directoryCount)} folders`
|
||||
|
||||
this.refs.summary.style.display = ''
|
||||
let fileSize
|
||||
try {
|
||||
fileSize = fs.statSync(this.path)?.size;
|
||||
} catch (e) {}
|
||||
if (fileSize == null) fileSize = -1
|
||||
this.refs.summary.textContent = `${humanize.fileSize(fileSize)} with ${fileLabel} and ${directoryLabel}`
|
||||
}
|
||||
|
||||
focusSelectedFile () {
|
||||
const selectedFile = this.refs.tree.querySelector('.selected')
|
||||
if (selectedFile) {
|
||||
selectedFile.focus()
|
||||
}
|
||||
}
|
||||
|
||||
selectFileBeforeIndex (index) {
|
||||
for (let i = index - 1; i >= 0; i--) {
|
||||
const previousEntry = this.entries[i]
|
||||
if (previousEntry instanceof FileView) {
|
||||
previousEntry.select()
|
||||
break
|
||||
} else {
|
||||
if (previousEntry.selectLastFile()) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selectFileAfterIndex (index) {
|
||||
for (let i = index + 1; i < this.entries.length; i++) {
|
||||
const nextEntry = this.entries[i]
|
||||
if (nextEntry instanceof FileView) {
|
||||
nextEntry.select()
|
||||
break
|
||||
} else {
|
||||
if (nextEntry.selectFirstFile()) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
focus () {
|
||||
this.focusSelectedFile()
|
||||
}
|
||||
}
|
74
packages/archive-view/lib/archive-editor.js
Normal file
74
packages/archive-view/lib/archive-editor.js
Normal file
@ -0,0 +1,74 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const {Disposable} = require('atom')
|
||||
|
||||
const getIconServices = require('./get-icon-services')
|
||||
const ArchiveEditorView = require('./archive-editor-view')
|
||||
|
||||
module.exports = {
|
||||
activate () {
|
||||
this.disposable = atom.workspace.addOpener((filePath = '') => {
|
||||
// Check that filePath exists before opening, in case a remote URI was given
|
||||
if (!isPathSupported(filePath)) return;
|
||||
let isFile = false
|
||||
try {
|
||||
isFile = fs.statSync(filePath)?.isFile()
|
||||
} catch (e) {}
|
||||
if (isFile) {
|
||||
return new ArchiveEditorView(filePath)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
deactivate () {
|
||||
this.disposable.dispose()
|
||||
for (const item of atom.workspace.getPaneItems()) {
|
||||
if (item instanceof ArchiveEditorView) {
|
||||
item.destroy()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
consumeElementIcons (service) {
|
||||
getIconServices().setElementIcons(service)
|
||||
return new Disposable(() => getIconServices().resetElementIcons())
|
||||
},
|
||||
|
||||
consumeFileIcons (service) {
|
||||
getIconServices().setFileIcons(service)
|
||||
return new Disposable(() => getIconServices().resetFileIcons())
|
||||
},
|
||||
|
||||
deserialize (params = {}) {
|
||||
let isFile = false
|
||||
try {
|
||||
isFile = fs.statSync(params.path)?.isFile()
|
||||
} catch (e) {}
|
||||
if (isFile) {
|
||||
return new ArchiveEditorView(params.path)
|
||||
} else {
|
||||
console.warn(`Can't build ArchiveEditorView for path "${params.path}"; file no longer exists`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isPathSupported (filePath) {
|
||||
switch (path.extname(filePath)) {
|
||||
case '.egg':
|
||||
case '.epub':
|
||||
case '.jar':
|
||||
case '.love':
|
||||
case '.nupkg':
|
||||
case '.tar':
|
||||
case '.tgz':
|
||||
case '.war':
|
||||
case '.whl':
|
||||
case '.xpi':
|
||||
case '.zip':
|
||||
return true
|
||||
case '.gz':
|
||||
return path.extname(path.basename(filePath, '.gz')) === '.tar'
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
36
packages/archive-view/lib/default-file-icons.js
Normal file
36
packages/archive-view/lib/default-file-icons.js
Normal file
@ -0,0 +1,36 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
class DefaultFileIcons {
|
||||
iconClassForPath (filePath) {
|
||||
const extension = path.extname(filePath).toLowerCase()
|
||||
const base = path.basename(filePath, extension).toLowerCase();
|
||||
|
||||
let isSymbolicLinkSync = false
|
||||
try {
|
||||
fs.lstatSync(filePath)?.isSymbolicLink();
|
||||
} catch (e) {}
|
||||
if (isSymbolicLinkSync) return 'icon-file-symlink-file'
|
||||
|
||||
if (base === 'readme' && ['','.markdown','.md','.mdown','.mkd','.mkdown','.rmd','.ron'].includes(extension)) {
|
||||
return 'icon-book'
|
||||
}
|
||||
|
||||
if (['.bz2','.egg','.epub','.gem','.gz','.jar','.lz','.lzma','.lzo','.rar','.tar','.tgz','.war','.whl','.xpi','.xz','.z','.zip'].includes(extension)) {
|
||||
return 'icon-file-zip'
|
||||
}
|
||||
|
||||
if (['.gif','.ico','.jpeg','.jpg','.png','.tif','.tiff','.webp'].includes(extension)) {
|
||||
return 'icon-file-media'
|
||||
}
|
||||
|
||||
if (extension === ".pdf") return 'icon-file-pdf'
|
||||
|
||||
if (['.ds_store','.a','.exe','.o','.pyc','.pyo','.so','.woff'].includes(extension)) {
|
||||
return 'icon-file-binary'
|
||||
}
|
||||
return 'icon-file-text'
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new DefaultFileIcons()
|
132
packages/archive-view/lib/directory-view.js
Normal file
132
packages/archive-view/lib/directory-view.js
Normal file
@ -0,0 +1,132 @@
|
||||
/** @babel */
|
||||
|
||||
import {CompositeDisposable, Disposable} from 'atom'
|
||||
|
||||
import FileView from './file-view'
|
||||
import getIconServices from './get-icon-services'
|
||||
|
||||
export default class DirectoryView {
|
||||
constructor (parentView, indexInParentView, archivePath, entry) {
|
||||
this.disposables = new CompositeDisposable()
|
||||
this.entries = []
|
||||
this.parentView = parentView
|
||||
this.indexInParentView = indexInParentView
|
||||
this.element = document.createElement('li')
|
||||
this.element.classList.add('list-nested-item', 'entry')
|
||||
|
||||
const listItem = document.createElement('span')
|
||||
listItem.classList.add('list-item')
|
||||
|
||||
const clickHandler = (event) => {
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
this.element.classList.toggle('collapsed')
|
||||
}
|
||||
listItem.addEventListener('click', clickHandler)
|
||||
this.disposables.add(new Disposable(() => { listItem.removeEventListener('click', clickHandler) }))
|
||||
|
||||
const entrySpan = document.createElement('span')
|
||||
entrySpan.textContent = entry.getName()
|
||||
listItem.appendChild(entrySpan)
|
||||
this.element.appendChild(listItem)
|
||||
|
||||
this.entry = entry
|
||||
this.entrySpan = entrySpan
|
||||
getIconServices().updateDirectoryIcon(this)
|
||||
|
||||
this.entriesTree = document.createElement('ol')
|
||||
this.entriesTree.classList.add('list-tree')
|
||||
let index = 0
|
||||
for (const child of entry.children) {
|
||||
if (child.isDirectory()) {
|
||||
const entryView = new DirectoryView(this, index, archivePath, child)
|
||||
this.entries.push(entryView)
|
||||
this.entriesTree.appendChild(entryView.element)
|
||||
} else {
|
||||
const entryView = new FileView(this, index, archivePath, child)
|
||||
this.entries.push(entryView)
|
||||
this.entriesTree.appendChild(entryView.element)
|
||||
}
|
||||
|
||||
index++
|
||||
}
|
||||
this.element.appendChild(this.entriesTree)
|
||||
}
|
||||
|
||||
destroy () {
|
||||
if (this.iconDisposable) {
|
||||
this.iconDisposable.dispose()
|
||||
this.iconDisposable = null
|
||||
}
|
||||
|
||||
while (this.entries.length > 0) {
|
||||
this.entries.pop().destroy()
|
||||
}
|
||||
|
||||
this.disposables.dispose()
|
||||
this.element.remove()
|
||||
}
|
||||
|
||||
selectFileBeforeIndex (index) {
|
||||
for (let i = index - 1; i >= 0; i--) {
|
||||
const previousEntry = this.entries[i]
|
||||
if (previousEntry instanceof FileView) {
|
||||
previousEntry.select()
|
||||
return
|
||||
} else {
|
||||
if (previousEntry.selectLastFile()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.parentView.selectFileBeforeIndex(this.indexInParentView)
|
||||
}
|
||||
|
||||
selectFileAfterIndex (index) {
|
||||
for (let i = index + 1; i < this.entries.length; i++) {
|
||||
const nextEntry = this.entries[i]
|
||||
if (nextEntry instanceof FileView) {
|
||||
nextEntry.select()
|
||||
return
|
||||
} else {
|
||||
if (nextEntry.selectFirstFile()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.parentView.selectFileAfterIndex(this.indexInParentView)
|
||||
}
|
||||
|
||||
selectFirstFile () {
|
||||
for (const entry of this.entries) {
|
||||
if (entry instanceof FileView) {
|
||||
entry.select()
|
||||
return true
|
||||
} else {
|
||||
if (entry.selectFirstFile()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
selectLastFile () {
|
||||
for (var i = this.entries.length - 1; i >= 0; i--) {
|
||||
const entry = this.entries[i]
|
||||
if (entry instanceof FileView) {
|
||||
entry.select()
|
||||
return true
|
||||
} else {
|
||||
if (entry.selectLastFile()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
112
packages/archive-view/lib/file-view.js
Normal file
112
packages/archive-view/lib/file-view.js
Normal file
@ -0,0 +1,112 @@
|
||||
/** @babel */
|
||||
|
||||
import {CompositeDisposable, Disposable} from 'atom'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import temp from 'temp'
|
||||
import archive from 'ls-archive'
|
||||
|
||||
import getIconServices from './get-icon-services'
|
||||
|
||||
export default class FileView {
|
||||
constructor (parentView, indexInParentView, archivePath, entry) {
|
||||
this.disposables = new CompositeDisposable()
|
||||
this.parentView = parentView
|
||||
this.indexInParentView = indexInParentView
|
||||
this.archivePath = archivePath
|
||||
this.entry = entry
|
||||
|
||||
this.element = document.createElement('li')
|
||||
this.element.classList.add('list-item', 'entry')
|
||||
this.element.tabIndex = -1
|
||||
|
||||
this.name = document.createElement('span')
|
||||
getIconServices().updateFileIcon(this)
|
||||
this.name.textContent = this.entry.getName()
|
||||
this.element.appendChild(this.name)
|
||||
|
||||
const clickHandler = () => {
|
||||
this.select()
|
||||
this.openFile()
|
||||
}
|
||||
this.element.addEventListener('click', clickHandler)
|
||||
this.disposables.add(new Disposable(() => { this.element.removeEventListener('click', clickHandler) }))
|
||||
|
||||
this.disposables.add(atom.commands.add(this.element, {
|
||||
'core:confirm': () => {
|
||||
if (this.isSelected()) {
|
||||
this.openFile()
|
||||
}
|
||||
},
|
||||
|
||||
'core:move-down': () => {
|
||||
if (this.isSelected()) {
|
||||
this.parentView.selectFileAfterIndex(this.indexInParentView)
|
||||
}
|
||||
},
|
||||
|
||||
'core:move-up': () => {
|
||||
if (this.isSelected()) {
|
||||
this.parentView.selectFileBeforeIndex(this.indexInParentView)
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
destroy () {
|
||||
this.disposables.dispose()
|
||||
this.element.remove()
|
||||
}
|
||||
|
||||
isSelected () {
|
||||
return this.element.classList.contains('selected')
|
||||
}
|
||||
|
||||
logError (message, error) {
|
||||
console.error(message, error.stack != null ? error.stack : error)
|
||||
}
|
||||
|
||||
openFile () {
|
||||
archive.readFile(this.archivePath, this.entry.getPath(), (error, contents) => {
|
||||
if (error != null) {
|
||||
this.logError(`Error reading: ${this.entry.getPath()} from ${this.archivePath}`, error)
|
||||
} else {
|
||||
temp.mkdir('atom-', (error, tempDirPath) => {
|
||||
if (error != null) {
|
||||
this.logError(`Error creating temp directory: ${tempDirPath}`, error)
|
||||
} else {
|
||||
const tempArchiveDirPath = path.join(tempDirPath, path.basename(this.archivePath))
|
||||
fs.mkdir(tempArchiveDirPath, {recursive:true}, error => {
|
||||
if (error != null) {
|
||||
this.logError(`Error creating archive directory ${tempArchiveDirPath}`, error)
|
||||
} else {
|
||||
const tempFilePath = path.join(tempArchiveDirPath, this.entry.getName())
|
||||
fs.writeFile(tempFilePath, contents, error => {
|
||||
if (error != null) {
|
||||
this.logError(`Error writing to ${tempFilePath}`, error)
|
||||
} else {
|
||||
atom.workspace.open(tempFilePath)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
select () {
|
||||
this.element.focus()
|
||||
|
||||
const archiveEditorElement = this.element.closest('.archive-editor')
|
||||
// On initial tree creation, it is not possible for any entries to be selected
|
||||
// (The entries also haven't been added to the DOM yet)
|
||||
if (archiveEditorElement) {
|
||||
for (const selected of archiveEditorElement.querySelectorAll('.selected')) {
|
||||
selected.classList.remove('selected')
|
||||
}
|
||||
}
|
||||
this.element.classList.add('selected')
|
||||
}
|
||||
}
|
72
packages/archive-view/lib/get-icon-services.js
Normal file
72
packages/archive-view/lib/get-icon-services.js
Normal file
@ -0,0 +1,72 @@
|
||||
const DefaultFileIcons = require('./default-file-icons')
|
||||
const {Emitter, CompositeDisposable} = require('atom')
|
||||
const path = require('path')
|
||||
|
||||
let iconServices
|
||||
module.exports = function getIconServices () {
|
||||
if (!iconServices) iconServices = new IconServices()
|
||||
return iconServices
|
||||
}
|
||||
|
||||
class IconServices {
|
||||
constructor () {
|
||||
this.emitter = new Emitter()
|
||||
this.elementIcons = null
|
||||
this.elementIconDisposables = new CompositeDisposable()
|
||||
this.fileIcons = DefaultFileIcons
|
||||
}
|
||||
|
||||
onDidChange (callback) {
|
||||
return this.emitter.on('did-change', callback)
|
||||
}
|
||||
|
||||
resetElementIcons () {
|
||||
this.setElementIcons(null)
|
||||
}
|
||||
|
||||
resetFileIcons () {
|
||||
this.setFileIcons(DefaultFileIcons)
|
||||
}
|
||||
|
||||
setElementIcons (service) {
|
||||
if (service !== this.elementIcons) {
|
||||
if (this.elementIconDisposables != null) {
|
||||
this.elementIconDisposables.dispose()
|
||||
}
|
||||
if (service) { this.elementIconDisposables = new CompositeDisposable() }
|
||||
this.elementIcons = service
|
||||
return this.emitter.emit('did-change')
|
||||
}
|
||||
}
|
||||
|
||||
setFileIcons (service) {
|
||||
if (service !== this.fileIcons) {
|
||||
this.fileIcons = service
|
||||
return this.emitter.emit('did-change')
|
||||
}
|
||||
}
|
||||
|
||||
updateDirectoryIcon (view) {
|
||||
view.entrySpan.classList.add('directory', 'icon', 'icon-file-directory')
|
||||
if (this.elementIcons) {
|
||||
view.iconDisposable = this.elementIcons(view.entrySpan, view.entry.path, {isDirectory: true})
|
||||
}
|
||||
}
|
||||
|
||||
updateFileIcon (view) {
|
||||
const nameClasses = ['file', 'icon']
|
||||
if (this.elementIcons) {
|
||||
const fullPath = path.join(view.archivePath, view.entry.path)
|
||||
const disposable = this.elementIcons(view.name, fullPath)
|
||||
view.disposables.add(disposable)
|
||||
this.elementIconDisposables.add(disposable)
|
||||
} else {
|
||||
let typeClass = this.fileIcons.iconClassForPath(view.entry.path, 'archive-view') || []
|
||||
if (!Array.isArray(typeClass) && typeClass) {
|
||||
typeClass = typeClass.toString().split(/\s+/g)
|
||||
}
|
||||
nameClasses.push(...typeClass)
|
||||
}
|
||||
view.name.classList.add(...nameClasses)
|
||||
}
|
||||
}
|
513
packages/archive-view/package-lock.json
generated
Normal file
513
packages/archive-view/package-lock.json
generated
Normal file
@ -0,0 +1,513 @@
|
||||
{
|
||||
"name": "archive-view",
|
||||
"version": "0.66.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "archive-view",
|
||||
"version": "0.66.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"etch": "^0.14.1",
|
||||
"humanize-plus": "~1.8.2",
|
||||
"ls-archive": "1.3.4",
|
||||
"temp": "^0.9.4"
|
||||
},
|
||||
"engines": {
|
||||
"atom": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "0.2.10",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
|
||||
"integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/block-stream": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
|
||||
"integrity": "sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ==",
|
||||
"dependencies": {
|
||||
"inherits": "~2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "0.4 || >=0.5.8"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-crc32": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/colors": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
|
||||
"integrity": "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw==",
|
||||
"engines": {
|
||||
"node": ">=0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/etch": {
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmjs.org/etch/-/etch-0.14.1.tgz",
|
||||
"integrity": "sha512-+IwqSDBhaQFMUHJu4L/ir0dhDoW5IIihg4Z9lzsIxxne8V0PlSg0gnk2STaKWjGJQnDR4cxpA+a/dORX9kycTA=="
|
||||
},
|
||||
"node_modules/fd-slicer": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
|
||||
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
|
||||
"dependencies": {
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/fstream": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
|
||||
"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"inherits": "~2.0.0",
|
||||
"mkdirp": ">=0.5 0",
|
||||
"rimraf": "2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.10",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
|
||||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
|
||||
},
|
||||
"node_modules/humanize-plus": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/humanize-plus/-/humanize-plus-1.8.2.tgz",
|
||||
"integrity": "sha512-jaLeQyyzjjINGv7O9JJegjsaUcWjSj/1dcXvLEgU3pGdqCdP1PiC/uwr+saJXhTNBHZtmKnmpXyazgh+eceRxA==",
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/ls-archive": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/ls-archive/-/ls-archive-1.3.4.tgz",
|
||||
"integrity": "sha512-7GmjZOckV+gzm4PM1/LcWIsZIRsSkAVmIchoEf5xjquNKU0Ti5KUvGQ3dl/7VsbZIduMOPwRDXrvpo3LVJ0Pmg==",
|
||||
"dependencies": {
|
||||
"async": "~0.2.9",
|
||||
"colors": "~0.6.2",
|
||||
"optimist": "~0.5.2",
|
||||
"rimraf": "~2.2.6",
|
||||
"tar": "^2.2.1",
|
||||
"yauzl": "^2.9.1"
|
||||
},
|
||||
"bin": {
|
||||
"lsa": "bin/lsa"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
|
||||
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.6"
|
||||
},
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/optimist": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.5.2.tgz",
|
||||
"integrity": "sha512-r9M8ZpnM9SXV5Wii7TCqienfcaY3tAiJe9Jchof87icbmbruKgK0xKXngmrnowTDnEawmmI1Qbha59JEoBkBGA==",
|
||||
"dependencies": {
|
||||
"wordwrap": "~0.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pend": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
|
||||
"integrity": "sha512-R5KMKHnPAQaZMqLOsyuyUmcIjSeDm+73eoqQpaXA7AZ22BL+6C+1mcUscgOsNd8WVlJuvlgAPsegcx7pjlV0Dg==",
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
|
||||
"integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
|
||||
"deprecated": "This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.",
|
||||
"dependencies": {
|
||||
"block-stream": "*",
|
||||
"fstream": "^1.0.12",
|
||||
"inherits": "2"
|
||||
}
|
||||
},
|
||||
"node_modules/temp": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz",
|
||||
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
|
||||
"dependencies": {
|
||||
"mkdirp": "^0.5.1",
|
||||
"rimraf": "~2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/temp/node_modules/rimraf": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
|
||||
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/wordwrap": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
|
||||
"integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/yauzl": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
||||
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
|
||||
"dependencies": {
|
||||
"buffer-crc32": "~0.2.3",
|
||||
"fd-slicer": "~1.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "0.2.10",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
|
||||
"integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"block-stream": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
|
||||
"integrity": "sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ==",
|
||||
"requires": {
|
||||
"inherits": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"buffer-crc32": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="
|
||||
},
|
||||
"colors": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
|
||||
"integrity": "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw=="
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"etch": {
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmjs.org/etch/-/etch-0.14.1.tgz",
|
||||
"integrity": "sha512-+IwqSDBhaQFMUHJu4L/ir0dhDoW5IIihg4Z9lzsIxxne8V0PlSg0gnk2STaKWjGJQnDR4cxpA+a/dORX9kycTA=="
|
||||
},
|
||||
"fd-slicer": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
|
||||
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
|
||||
"requires": {
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"fstream": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
|
||||
"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"inherits": "~2.0.0",
|
||||
"mkdirp": ">=0.5 0",
|
||||
"rimraf": "2"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.10",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
|
||||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
|
||||
},
|
||||
"humanize-plus": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/humanize-plus/-/humanize-plus-1.8.2.tgz",
|
||||
"integrity": "sha512-jaLeQyyzjjINGv7O9JJegjsaUcWjSj/1dcXvLEgU3pGdqCdP1PiC/uwr+saJXhTNBHZtmKnmpXyazgh+eceRxA=="
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"ls-archive": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/ls-archive/-/ls-archive-1.3.4.tgz",
|
||||
"integrity": "sha512-7GmjZOckV+gzm4PM1/LcWIsZIRsSkAVmIchoEf5xjquNKU0Ti5KUvGQ3dl/7VsbZIduMOPwRDXrvpo3LVJ0Pmg==",
|
||||
"requires": {
|
||||
"async": "~0.2.9",
|
||||
"colors": "~0.6.2",
|
||||
"optimist": "~0.5.2",
|
||||
"rimraf": "~2.2.6",
|
||||
"tar": "^2.2.1",
|
||||
"yauzl": "^2.9.1"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
|
||||
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g=="
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.6"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"optimist": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.5.2.tgz",
|
||||
"integrity": "sha512-r9M8ZpnM9SXV5Wii7TCqienfcaY3tAiJe9Jchof87icbmbruKgK0xKXngmrnowTDnEawmmI1Qbha59JEoBkBGA==",
|
||||
"requires": {
|
||||
"wordwrap": "~0.0.2"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
|
||||
},
|
||||
"pend": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
|
||||
"integrity": "sha512-R5KMKHnPAQaZMqLOsyuyUmcIjSeDm+73eoqQpaXA7AZ22BL+6C+1mcUscgOsNd8WVlJuvlgAPsegcx7pjlV0Dg=="
|
||||
},
|
||||
"tar": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
|
||||
"integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
|
||||
"requires": {
|
||||
"block-stream": "*",
|
||||
"fstream": "^1.0.12",
|
||||
"inherits": "2"
|
||||
}
|
||||
},
|
||||
"temp": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz",
|
||||
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
|
||||
"requires": {
|
||||
"mkdirp": "^0.5.1",
|
||||
"rimraf": "~2.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"rimraf": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
|
||||
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
|
||||
"integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw=="
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"yauzl": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
||||
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
|
||||
"requires": {
|
||||
"buffer-crc32": "~0.2.3",
|
||||
"fd-slicer": "~1.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
33
packages/archive-view/package.json
Normal file
33
packages/archive-view/package.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "archive-view",
|
||||
"version": "0.66.0",
|
||||
"description": "View the files and folders inside archive files",
|
||||
"main": "./lib/archive-editor",
|
||||
"dependencies": {
|
||||
"etch": "^0.14.1",
|
||||
"humanize-plus": "~1.8.2",
|
||||
"ls-archive": "1.3.4",
|
||||
"temp": "^0.9.4"
|
||||
},
|
||||
"repository": "https://github.com/pulsar-edit/pulsar",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"atom": "*"
|
||||
},
|
||||
"deserializers": {
|
||||
"ArchiveEditor": "deserialize",
|
||||
"ArchiveEditorView": "deserialize"
|
||||
},
|
||||
"consumedServices": {
|
||||
"atom.file-icons": {
|
||||
"versions": {
|
||||
"1.0.0": "consumeFileIcons"
|
||||
}
|
||||
},
|
||||
"file-icons.element-icons": {
|
||||
"versions": {
|
||||
"1.0.0": "consumeElementIcons"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
packages/archive-view/resources/preview.png
Normal file
BIN
packages/archive-view/resources/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
46
packages/archive-view/spec/archive-editor-spec.js
Normal file
46
packages/archive-view/spec/archive-editor-spec.js
Normal file
@ -0,0 +1,46 @@
|
||||
const {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} = require('./async-spec-helpers') // eslint-disable-line no-unused-vars
|
||||
|
||||
const path = require('path')
|
||||
const ArchiveEditor = require('../lib/archive-editor')
|
||||
const ArchiveEditorView = require('../lib/archive-editor-view')
|
||||
|
||||
describe('ArchiveEditor', () => {
|
||||
const tarPath = path.join(__dirname, 'fixtures', 'nested.tar')
|
||||
|
||||
// Don't log during specs
|
||||
beforeEach(() => spyOn(console, 'warn'))
|
||||
|
||||
describe('.deserialize', () => {
|
||||
it('returns undefined if no file exists at the given path', () => {
|
||||
const editor1 = new ArchiveEditorView(tarPath)
|
||||
const state = editor1.serialize()
|
||||
editor1.destroy()
|
||||
|
||||
const editor2 = ArchiveEditor.deserialize(state)
|
||||
expect(editor2).toBeDefined()
|
||||
editor2.destroy()
|
||||
|
||||
state.path = 'bogus'
|
||||
expect(ArchiveEditor.deserialize(state)).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('.deactivate()', () => {
|
||||
it('removes all ArchiveEditorViews from the workspace and does not open any new ones', async () => {
|
||||
const getArchiveEditorViews = () => {
|
||||
return atom.workspace.getPaneItems().filter(item => item instanceof ArchiveEditorView)
|
||||
}
|
||||
await atom.packages.activatePackage('archive-view')
|
||||
await atom.workspace.open(path.join(__dirname, 'fixtures', 'nested.tar'))
|
||||
await atom.workspace.open(path.join(__dirname, 'fixtures', 'invalid.zip'))
|
||||
await atom.workspace.open()
|
||||
expect(getArchiveEditorViews().length).toBe(2)
|
||||
|
||||
await atom.packages.deactivatePackage('archive-view')
|
||||
expect(getArchiveEditorViews().length).toBe(0)
|
||||
|
||||
await atom.workspace.open(path.join(__dirname, 'fixtures', 'nested.tar'))
|
||||
expect(getArchiveEditorViews().length).toBe(0)
|
||||
})
|
||||
})
|
||||
})
|
276
packages/archive-view/spec/archive-editor-view-spec.js
Normal file
276
packages/archive-view/spec/archive-editor-view-spec.js
Normal file
@ -0,0 +1,276 @@
|
||||
const {Disposable, File} = require('atom')
|
||||
const getIconServices = require('../lib/get-icon-services')
|
||||
const {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} = require('./async-spec-helpers') // eslint-disable-line no-unused-vars
|
||||
|
||||
async function condition (handler) {
|
||||
if (jasmine.isSpy(window.setTimeout)) {
|
||||
jasmine.useRealClock()
|
||||
}
|
||||
return conditionPromise(handler)
|
||||
}
|
||||
|
||||
describe('ArchiveEditorView', () => {
|
||||
let archiveEditorView, onDidChangeCallback, onDidRenameCallback, onDidDeleteCallback
|
||||
|
||||
beforeEach(async () => {
|
||||
spyOn(File.prototype, 'onDidChange').andCallFake(function (callback) {
|
||||
if (/\.tar$/.test(this.getPath())) {
|
||||
onDidChangeCallback = callback
|
||||
}
|
||||
return new Disposable()
|
||||
})
|
||||
|
||||
spyOn(File.prototype, 'onDidRename').andCallFake(function (callback) {
|
||||
if (/\.tar$/.test(this.getPath())) {
|
||||
onDidRenameCallback = callback
|
||||
}
|
||||
return new Disposable()
|
||||
})
|
||||
|
||||
spyOn(File.prototype, 'onDidDelete').andCallFake(function (callback) {
|
||||
if (/\.tar$/.test(this.getPath())) {
|
||||
onDidDeleteCallback = callback
|
||||
}
|
||||
return new Disposable()
|
||||
})
|
||||
|
||||
await atom.packages.activatePackage('archive-view')
|
||||
archiveEditorView = await atom.workspace.open('nested.tar')
|
||||
})
|
||||
|
||||
describe('.constructor()', () => {
|
||||
it('displays the files and folders in the archive file', async () => {
|
||||
expect(archiveEditorView.element).toExist()
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
|
||||
const directoryElements = archiveEditorView.element.querySelectorAll('.directory')
|
||||
expect(directoryElements.length).toBe(6)
|
||||
expect(directoryElements[0].textContent).toBe('d1')
|
||||
expect(directoryElements[1].textContent).toBe('d2')
|
||||
expect(directoryElements[2].textContent).toBe('d3')
|
||||
expect(directoryElements[3].textContent).toBe('d4')
|
||||
expect(directoryElements[4].textContent).toBe('da')
|
||||
expect(directoryElements[5].textContent).toBe('db')
|
||||
|
||||
const fileElements = archiveEditorView.element.querySelectorAll('.file')
|
||||
expect(fileElements.length).toBe(3)
|
||||
expect(fileElements[0].textContent).toBe('f1.txt')
|
||||
expect(fileElements[1].textContent).toBe('f2.txt')
|
||||
expect(fileElements[2].textContent).toBe('fa.txt')
|
||||
})
|
||||
|
||||
it('selects the first file', async () => {
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
expect(archiveEditorView.element.querySelector('.selected').textContent).toBe('f1.txt')
|
||||
})
|
||||
})
|
||||
|
||||
describe('.copy()', () => {
|
||||
it('returns a new ArchiveEditorView for the same file', () => {
|
||||
const newArchiveView = archiveEditorView.copy()
|
||||
expect(newArchiveView.getPath()).toBe(archiveEditorView.getPath())
|
||||
})
|
||||
})
|
||||
|
||||
describe('archive summary', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.workspace.open('multiple-entries.zip')
|
||||
archiveEditorView = atom.workspace.getActivePaneItem()
|
||||
jasmine.attachToDOM(atom.views.getView(atom.workspace))
|
||||
})
|
||||
|
||||
it('shows correct statistics', async () => {
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
const heading = archiveEditorView.element.querySelector('.inset-panel .panel-heading')
|
||||
expect(heading).not.toBe(null)
|
||||
expect(heading.textContent).toBe('704 bytes with 4 files and 1 folder')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when core:move-up/core:move-down is triggered', () => {
|
||||
let selectedEntry
|
||||
const dispatch = (command) => {
|
||||
atom.commands.dispatch(archiveEditorView.element.querySelector('.selected'), command)
|
||||
selectedEntry = archiveEditorView.element.querySelector('.selected').textContent
|
||||
return true
|
||||
}
|
||||
|
||||
it('selects the next/previous file', async () => {
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
expect(archiveEditorView.element).toBeDefined()
|
||||
dispatch('core:move-up') && expect(selectedEntry).toBe('f1.txt')
|
||||
dispatch('core:move-down') && expect(selectedEntry).toBe('f2.txt')
|
||||
dispatch('core:move-down') && expect(selectedEntry).toBe('fa.txt')
|
||||
dispatch('core:move-down') && expect(selectedEntry).toBe('fa.txt')
|
||||
dispatch('core:move-up') && expect(selectedEntry).toBe('f2.txt')
|
||||
dispatch('core:move-up') && expect(selectedEntry).toBe('f1.txt')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when a file is clicked', () => {
|
||||
it('copies the contents to a temp file and opens it in a new editor', async () => {
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
archiveEditorView.element.querySelectorAll('.file')[2].click()
|
||||
await condition(() => atom.workspace.getActivePane().getItems().length > 1)
|
||||
expect(atom.workspace.getActivePaneItem().getText()).toBe('hey there\n')
|
||||
expect(atom.workspace.getActivePaneItem().getTitle()).toBe('fa.txt')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when a directory is clicked', () => {
|
||||
it('collapses/expands itself', async () => {
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
let directory = archiveEditorView.element.querySelectorAll('.list-nested-item.entry')[0]
|
||||
expect(directory.classList.contains('collapsed')).toBeFalsy()
|
||||
directory.querySelector('.list-item').click()
|
||||
expect(directory.classList.contains('collapsed')).toBeTruthy()
|
||||
directory.querySelector('.list-item').click()
|
||||
expect(directory.classList.contains('collapsed')).toBeFalsy()
|
||||
})
|
||||
})
|
||||
|
||||
describe('when core:confirm is triggered', () => {
|
||||
it('copies the contents to a temp file and opens it in a new editor', async () => {
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
atom.commands.dispatch(archiveEditorView.element.querySelector('.file'), 'core:confirm')
|
||||
await condition(() => atom.workspace.getActivePane().getItems().length > 1)
|
||||
expect(atom.workspace.getActivePaneItem().getText()).toBe('')
|
||||
expect(atom.workspace.getActivePaneItem().getTitle()).toBe('f1.txt')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the file is modified', () => {
|
||||
it('refreshes the view', async () => {
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
spyOn(archiveEditorView, 'refresh')
|
||||
onDidChangeCallback()
|
||||
expect(archiveEditorView.refresh).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the file is renamed', () => {
|
||||
it('refreshes the view and updates the title', async () => {
|
||||
spyOn(File.prototype, 'getPath').andReturn('nested-renamed.tar')
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
spyOn(archiveEditorView, 'refresh').andCallThrough()
|
||||
spyOn(archiveEditorView, 'getTitle')
|
||||
onDidRenameCallback()
|
||||
expect(archiveEditorView.refresh).toHaveBeenCalled()
|
||||
expect(archiveEditorView.getTitle).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the file is removed', () => {
|
||||
it('destroys the view', async () => {
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
expect(atom.workspace.getActivePane().getItems().length).toBe(1)
|
||||
onDidDeleteCallback()
|
||||
expect(atom.workspace.getActivePaneItem()).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the file is invalid', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.workspace.open('invalid.zip')
|
||||
archiveEditorView = atom.workspace.getActivePaneItem()
|
||||
jasmine.attachToDOM(atom.views.getView(atom.workspace))
|
||||
})
|
||||
|
||||
it('shows the error', async () => {
|
||||
await condition(() => archiveEditorView.refs.errorMessage.offsetHeight > 0)
|
||||
expect(archiveEditorView.refs.errorMessage.textContent.length).toBeGreaterThan(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('FileIcons', () => {
|
||||
async function openFile () {
|
||||
await atom.workspace.open('file-icons.zip')
|
||||
archiveEditorView = atom.workspace.getActivePaneItem()
|
||||
jasmine.attachToDOM(atom.views.getView(atom.workspace))
|
||||
}
|
||||
|
||||
describe('Icon service', () => {
|
||||
const service = { iconClassForPath () {} }
|
||||
beforeEach(() => openFile())
|
||||
|
||||
it('provides a default service', () => {
|
||||
expect(getIconServices().fileIcons).toBeDefined()
|
||||
expect(getIconServices().fileIcons).not.toBeNull()
|
||||
})
|
||||
|
||||
it('allows the default to be overridden', () => {
|
||||
getIconServices().setFileIcons(service)
|
||||
expect(getIconServices().fileIcons).toBe(service)
|
||||
})
|
||||
|
||||
it('allows service to be reset without hassle', () => {
|
||||
getIconServices().setFileIcons(service)
|
||||
getIconServices().resetFileIcons()
|
||||
expect(getIconServices().fileIcons).not.toBe(service)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Class handling', () => {
|
||||
function findEntryContainingText (text) {
|
||||
for (const entry of archiveEditorView.element.querySelectorAll('.list-item.entry')) {
|
||||
if (entry.textContent.includes(text)) { return entry }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function checkMultiClass () {
|
||||
expect(findEntryContainingText('adobe.pdf').querySelector('.file.icon').className).toBe('file icon text pdf-icon document')
|
||||
expect(findEntryContainingText('spacer.gif').querySelector('.file.icon').className).toBe('file icon binary gif-icon image')
|
||||
expect(findEntryContainingText('font.ttf').querySelector('.file.icon').className).toBe('file icon binary ttf-icon font')
|
||||
}
|
||||
|
||||
it('displays default file-icons', async () => {
|
||||
await openFile()
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
expect(findEntryContainingText('adobe.pdf').querySelector('.file.icon.icon-file-pdf').length).not.toBe(0)
|
||||
expect(findEntryContainingText('spacer.gif').querySelector('.file.icon.icon-file-media').length).not.toBe(0)
|
||||
expect(findEntryContainingText('sunn.o').querySelector('.file.icon.icon-file-binary').length).not.toBe(0)
|
||||
})
|
||||
|
||||
it('allows multiple classes to be passed', async () => {
|
||||
getIconServices().setFileIcons({
|
||||
iconClassForPath: (path) => {
|
||||
switch (path.match(/\w*$/)[0]) {
|
||||
case 'pdf': return 'text pdf-icon document'
|
||||
case 'ttf': return 'binary ttf-icon font'
|
||||
case 'gif': return 'binary gif-icon image'
|
||||
}
|
||||
}
|
||||
})
|
||||
await openFile()
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
checkMultiClass()
|
||||
})
|
||||
|
||||
it('allows an array of classes to be passed', async () => {
|
||||
getIconServices().setFileIcons({
|
||||
iconClassForPath: (path) => {
|
||||
switch (path.match(/\w*$/)[0]) {
|
||||
case 'pdf': return ['text', 'pdf-icon', 'document']
|
||||
case 'ttf': return ['binary', 'ttf-icon', 'font']
|
||||
case 'gif': return ['binary', 'gif-icon', 'image']
|
||||
}
|
||||
}
|
||||
})
|
||||
await openFile()
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
checkMultiClass()
|
||||
})
|
||||
|
||||
it('identifies context to icon-service providers', async () => {
|
||||
getIconServices().setFileIcons({
|
||||
iconClassForPath: (path, context) => `icon-${context}`
|
||||
})
|
||||
await openFile()
|
||||
await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0)
|
||||
const icons = findEntryContainingText('adobe.pdf').querySelectorAll('.file.icon-archive-view')
|
||||
expect(icons.length).not.toBe(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
103
packages/archive-view/spec/async-spec-helpers.js
Normal file
103
packages/archive-view/spec/async-spec-helpers.js
Normal file
@ -0,0 +1,103 @@
|
||||
/** @babel */
|
||||
|
||||
export function beforeEach (fn) {
|
||||
global.beforeEach(function () {
|
||||
const result = fn()
|
||||
if (result instanceof Promise) {
|
||||
waitsForPromise(() => result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function afterEach (fn) {
|
||||
global.afterEach(function () {
|
||||
const result = fn()
|
||||
if (result instanceof Promise) {
|
||||
waitsForPromise(() => result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
['it', 'fit', 'ffit', 'fffit'].forEach(function (name) {
|
||||
module.exports[name] = function (description, fn) {
|
||||
if (fn === undefined) {
|
||||
global[name](description)
|
||||
return
|
||||
}
|
||||
|
||||
global[name](description, function () {
|
||||
const result = fn()
|
||||
if (result instanceof Promise) {
|
||||
waitsForPromise(() => result)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export async function conditionPromise (condition, description = 'anonymous condition') {
|
||||
const startTime = Date.now()
|
||||
|
||||
while (true) {
|
||||
await timeoutPromise(100)
|
||||
|
||||
if (await condition()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (Date.now() - startTime > 5000) {
|
||||
throw new Error('Timed out waiting on ' + description)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function timeoutPromise (timeout) {
|
||||
return new Promise(function (resolve) {
|
||||
global.setTimeout(resolve, timeout)
|
||||
})
|
||||
}
|
||||
|
||||
function waitsForPromise (fn) {
|
||||
const promise = fn()
|
||||
global.waitsFor('spec promise to resolve', function (done) {
|
||||
promise.then(done, function (error) {
|
||||
jasmine.getEnv().currentSpec.fail(error)
|
||||
done()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function emitterEventPromise (emitter, event, timeout = 15000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeoutHandle = setTimeout(() => {
|
||||
reject(new Error(`Timed out waiting for '${event}' event`))
|
||||
}, timeout)
|
||||
emitter.once(event, () => {
|
||||
clearTimeout(timeoutHandle)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function promisify (original) {
|
||||
return function (...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
args.push((err, ...results) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(...results)
|
||||
}
|
||||
})
|
||||
|
||||
return original(...args)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function promisifySome (obj, fnNames) {
|
||||
const result = {}
|
||||
for (const fnName of fnNames) {
|
||||
result[fnName] = promisify(obj[fnName])
|
||||
}
|
||||
return result
|
||||
}
|
BIN
packages/archive-view/spec/fixtures/file-icons.zip
vendored
Normal file
BIN
packages/archive-view/spec/fixtures/file-icons.zip
vendored
Normal file
Binary file not shown.
1
packages/archive-view/spec/fixtures/invalid.zip
vendored
Normal file
1
packages/archive-view/spec/fixtures/invalid.zip
vendored
Normal file
@ -0,0 +1 @@
|
||||
invalid
|
BIN
packages/archive-view/spec/fixtures/multiple-entries.zip
vendored
Normal file
BIN
packages/archive-view/spec/fixtures/multiple-entries.zip
vendored
Normal file
Binary file not shown.
BIN
packages/archive-view/spec/fixtures/nested.tar
vendored
Normal file
BIN
packages/archive-view/spec/fixtures/nested.tar
vendored
Normal file
Binary file not shown.
24
packages/archive-view/styles/archive-view.less
Normal file
24
packages/archive-view/styles/archive-view.less
Normal file
@ -0,0 +1,24 @@
|
||||
@import "ui-variables";
|
||||
|
||||
.archive-editor {
|
||||
background-color: @inset-panel-background-color;
|
||||
overflow: auto;
|
||||
contain: strict;
|
||||
|
||||
.archive-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.inset-panel {
|
||||
border-width: 0;
|
||||
|
||||
.panel-heading {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.archive-tree {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
Copyright (c) 2014 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,8 +1,8 @@
|
||||
# Atom Dark Syntax theme
|
||||
# Pulsar Dark Syntax theme
|
||||
|
||||
A dark syntax theme for Atom.
|
||||
A dark syntax theme for Pulsar.
|
||||
|
||||
This theme is installed by default with Atom and can be activated by going to
|
||||
This theme is installed by default with Pulsar and can be activated by going to
|
||||
the _Themes_ section in the Settings view (`cmd-,`) and selecting it from the
|
||||
_Syntax Themes_ dropdown menu.
|
||||
|
||||
|
16
packages/atom-dark-syntax/package-lock.json
generated
Normal file
16
packages/atom-dark-syntax/package-lock.json
generated
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "atom-dark-syntax",
|
||||
"version": "0.29.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "atom-dark-syntax",
|
||||
"version": "0.29.1",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"atom": ">0.50.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
Copyright (c) 2014 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,8 +1,8 @@
|
||||
# Atom Dark UI theme
|
||||
# Pulsar Dark UI theme
|
||||
|
||||
A dark UI theme for Atom.
|
||||
A dark UI theme for Pulsar.
|
||||
|
||||
This theme is installed by default with Atom and can be activated by going to
|
||||
This theme is installed by default with Pulsar and can be activated by going to
|
||||
the _Themes_ section in the Settings view (`cmd-,`) and selecting it from the
|
||||
_UI Themes_ drop-down menu.
|
||||
|
||||
|
16
packages/atom-dark-ui/package-lock.json
generated
Normal file
16
packages/atom-dark-ui/package-lock.json
generated
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "atom-dark-ui",
|
||||
"version": "0.53.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "atom-dark-ui",
|
||||
"version": "0.53.3",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"atom": ">0.40.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
Copyright (c) 2014 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,8 +1,8 @@
|
||||
# Atom Light Syntax theme
|
||||
# Pulsar Light Syntax theme
|
||||
|
||||
A light syntax theme for Atom.
|
||||
A light syntax theme for Pulsar.
|
||||
|
||||
This theme is installed by default with Atom and can be activated by going to
|
||||
This theme is installed by default with Pulsar and can be activated by going to
|
||||
the _Themes_ section in the Settings view (`cmd-,`) and selecting it from the
|
||||
_Syntax Themes_ dropdown menu.
|
||||
|
||||
|
16
packages/atom-light-syntax/package-lock.json
generated
Normal file
16
packages/atom-light-syntax/package-lock.json
generated
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "atom-light-syntax",
|
||||
"version": "0.29.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "atom-light-syntax",
|
||||
"version": "0.29.1",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"atom": ">0.40.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
Copyright (c) 2014 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,8 +1,8 @@
|
||||
# Atom Light UI theme
|
||||
# Pulsar Light UI theme
|
||||
|
||||
A light UI theme for Atom.
|
||||
A light UI theme for Pulsar.
|
||||
|
||||
This theme is installed by default with Atom and can be activated by going to
|
||||
This theme is installed by default with Pulsar and can be activated by going to
|
||||
the _Themes_ section in the Settings view (`cmd-,`) and selecting it from the
|
||||
_UI Themes_ drop-down menu.
|
||||
|
||||
|
16
packages/atom-light-ui/package-lock.json
generated
Normal file
16
packages/atom-light-ui/package-lock.json
generated
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "atom-light-ui",
|
||||
"version": "0.46.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "atom-light-ui",
|
||||
"version": "0.46.3",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"atom": ">0.50.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
packages/autocomplete-css/.gitignore
vendored
Normal file
1
packages/autocomplete-css/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
12
packages/autocomplete-css/README.md
Normal file
12
packages/autocomplete-css/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# CSS Autocomplete package
|
||||
|
||||
CSS property name and value autocompletions in Pulsar. Uses the
|
||||
[autocomplete-plus](https://github.com/pulsar-edit/autocomplete-plus) package.
|
||||
|
||||
This is powered by the list of CSS property and values [here](https://github.com/adobe/brackets/blob/master/src/extensions/default/CSSCodeHints/CSSProperties.json).
|
||||
|
||||
![css-completions](https://cloud.githubusercontent.com/assets/671378/6357910/b9ecbe7c-bc1c-11e4-89b1-033e626c891f.gif)
|
||||
|
||||
You can update the prebuilt list of property names and values by running the `update.coffee` file at the root of the repository and then checking in the changed `properties.json` file.
|
||||
|
||||
`sorted-property-names.json` is updated manually - take a look at https://developer.microsoft.com/en-us/microsoft-edge/platform/usage/ and https://www.chromestatus.com/metrics/css/popularity for guidance.
|
2225
packages/autocomplete-css/completions.json
Normal file
2225
packages/autocomplete-css/completions.json
Normal file
File diff suppressed because it is too large
Load Diff
85
packages/autocomplete-css/fetch-property-docs.coffee
Normal file
85
packages/autocomplete-css/fetch-property-docs.coffee
Normal file
@ -0,0 +1,85 @@
|
||||
path = require 'path'
|
||||
fs = require 'fs'
|
||||
request = require 'request'
|
||||
|
||||
mdnCSSURL = 'https://developer.mozilla.org/en-US/docs/Web/CSS'
|
||||
mdnJSONAPI = 'https://developer.mozilla.org/en-US/search.json?topic=css&highlight=false'
|
||||
PropertiesURL = 'https://raw.githubusercontent.com/adobe/brackets/master/src/extensions/default/CSSCodeHints/CSSProperties.json'
|
||||
|
||||
fetch = ->
|
||||
propertiesPromise = new Promise (resolve) ->
|
||||
request {json: true, url: PropertiesURL}, (error, response, properties) ->
|
||||
if error?
|
||||
console.error(error.message)
|
||||
resolve(null)
|
||||
|
||||
if response.statusCode isnt 200
|
||||
console.error("Request for CSSProperties.json failed: #{response.statusCode}")
|
||||
resolve(null)
|
||||
|
||||
resolve(properties)
|
||||
|
||||
propertiesPromise.then (properties) ->
|
||||
return unless properties?
|
||||
|
||||
MAX = 10
|
||||
queue = Object.keys(properties)
|
||||
running = []
|
||||
docs = {}
|
||||
|
||||
new Promise (resolve) ->
|
||||
checkEnd = ->
|
||||
resolve(docs) if queue.length is 0 and running.length is 0
|
||||
|
||||
removeRunning = (propertyName) ->
|
||||
index = running.indexOf(propertyName)
|
||||
running.splice(index, 1) if index > -1
|
||||
|
||||
runNext = ->
|
||||
checkEnd()
|
||||
if queue.length isnt 0
|
||||
propertyName = queue.pop()
|
||||
running.push(propertyName)
|
||||
run(propertyName)
|
||||
|
||||
run = (propertyName) ->
|
||||
url = "#{mdnJSONAPI}&q=#{propertyName}"
|
||||
request {json: true, url}, (error, response, searchResults) ->
|
||||
if not error? and response.statusCode is 200
|
||||
handleRequest(propertyName, searchResults)
|
||||
else
|
||||
console.error "Req failed #{url}; #{response.statusCode}, #{error}"
|
||||
removeRunning(propertyName)
|
||||
checkEnd()
|
||||
runNext()
|
||||
|
||||
handleRequest = (propertyName, searchResults) ->
|
||||
if searchResults.documents?
|
||||
for doc in searchResults.documents
|
||||
if doc.url is "#{mdnCSSURL}/#{propertyName}"
|
||||
docs[propertyName] = filterExcerpt(propertyName, doc.excerpt)
|
||||
break
|
||||
return
|
||||
|
||||
runNext() for [0..MAX]
|
||||
return
|
||||
|
||||
filterExcerpt = (propertyName, excerpt) ->
|
||||
beginningPattern = /^the (css )?[a-z-]+ (css )?property (is )?(\w+)/i
|
||||
excerpt = excerpt.replace beginningPattern, (match) ->
|
||||
matches = beginningPattern.exec(match)
|
||||
firstWord = matches[4]
|
||||
firstWord[0].toUpperCase() + firstWord.slice(1)
|
||||
periodIndex = excerpt.indexOf('.')
|
||||
excerpt = excerpt.slice(0, periodIndex + 1) if periodIndex > -1
|
||||
excerpt
|
||||
|
||||
# Save a file if run from the command line
|
||||
if require.main is module
|
||||
fetch().then (docs) ->
|
||||
if docs?
|
||||
fs.writeFileSync(path.join(__dirname, 'property-docs.json'), "#{JSON.stringify(docs, null, ' ')}\n")
|
||||
else
|
||||
console.error 'No docs'
|
||||
|
||||
module.exports = fetch
|
114
packages/autocomplete-css/html-tags.json
Normal file
114
packages/autocomplete-css/html-tags.json
Normal file
@ -0,0 +1,114 @@
|
||||
[
|
||||
"a",
|
||||
"b",
|
||||
"blockquote",
|
||||
"body",
|
||||
"br",
|
||||
"button",
|
||||
"canvas",
|
||||
"code",
|
||||
"div",
|
||||
"em",
|
||||
"form",
|
||||
"footer",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
"head",
|
||||
"header",
|
||||
"hgroup",
|
||||
"hr",
|
||||
"html",
|
||||
"i",
|
||||
"iframe",
|
||||
"img",
|
||||
"input",
|
||||
"label",
|
||||
"li",
|
||||
"nav",
|
||||
"ol",
|
||||
"p",
|
||||
"pre",
|
||||
"select",
|
||||
"span",
|
||||
"strong",
|
||||
"sub",
|
||||
"summary",
|
||||
"table",
|
||||
"td",
|
||||
"textarea",
|
||||
"th",
|
||||
"title",
|
||||
"tr",
|
||||
"ul",
|
||||
"abbr",
|
||||
"address",
|
||||
"area",
|
||||
"article",
|
||||
"aside",
|
||||
"audio",
|
||||
"base",
|
||||
"bdi",
|
||||
"bdo",
|
||||
"big",
|
||||
"caption",
|
||||
"cite",
|
||||
"col",
|
||||
"colgroup",
|
||||
"command",
|
||||
"datalist",
|
||||
"dd",
|
||||
"del",
|
||||
"details",
|
||||
"dfn",
|
||||
"dialog",
|
||||
"dl",
|
||||
"dt",
|
||||
"embed",
|
||||
"fieldset",
|
||||
"figcaption",
|
||||
"figure",
|
||||
"ilayer",
|
||||
"ins",
|
||||
"kbd",
|
||||
"keygen",
|
||||
"legend",
|
||||
"link",
|
||||
"main",
|
||||
"map",
|
||||
"mark",
|
||||
"marquee",
|
||||
"menu",
|
||||
"meta",
|
||||
"meter",
|
||||
"noscript",
|
||||
"object",
|
||||
"optgroup",
|
||||
"option",
|
||||
"output",
|
||||
"param",
|
||||
"progress",
|
||||
"q",
|
||||
"rp",
|
||||
"rt",
|
||||
"ruby",
|
||||
"samp",
|
||||
"script",
|
||||
"section",
|
||||
"small",
|
||||
"source",
|
||||
"style",
|
||||
"sup",
|
||||
"tbody",
|
||||
"tfoot",
|
||||
"thead",
|
||||
"time",
|
||||
"track",
|
||||
"tt",
|
||||
"var",
|
||||
"video",
|
||||
"wbr"
|
||||
]
|
6
packages/autocomplete-css/lib/main.coffee
Normal file
6
packages/autocomplete-css/lib/main.coffee
Normal file
@ -0,0 +1,6 @@
|
||||
provider = require './provider'
|
||||
|
||||
module.exports =
|
||||
activate: ->
|
||||
|
||||
getProvider: -> provider
|
318
packages/autocomplete-css/lib/provider.coffee
Normal file
318
packages/autocomplete-css/lib/provider.coffee
Normal file
@ -0,0 +1,318 @@
|
||||
COMPLETIONS = require('../completions.json')
|
||||
|
||||
firstInlinePropertyNameWithColonPattern = /{\s*(\S+)\s*:/ # .example { display: }
|
||||
inlinePropertyNameWithColonPattern = /(?:;.+?)*;\s*(\S+)\s*:/ # .example { display: block; float: left; color: } (match the last one)
|
||||
propertyNameWithColonPattern = /^\s*(\S+)\s*:/ # display:
|
||||
propertyNamePrefixPattern = /[a-zA-Z]+[-a-zA-Z]*$/
|
||||
pseudoSelectorPrefixPattern = /:(:)?([a-z]+[a-z-]*)?$/
|
||||
tagSelectorPrefixPattern = /(^|\s|,)([a-z]+)?$/
|
||||
importantPrefixPattern = /(![a-z]+)$/
|
||||
cssDocsURL = "https://developer.mozilla.org/en-US/docs/Web/CSS"
|
||||
|
||||
module.exports =
|
||||
selector: '.source.css, .source.sass, .source.css.postcss'
|
||||
disableForSelector: '.source.css .comment, .source.css .string, .source.sass .comment, .source.sass .string, .source.css.postcss .comment, source.css.postcss .string'
|
||||
properties: COMPLETIONS.properties
|
||||
pseudoSelectors: COMPLETIONS.pseudoSelectors
|
||||
tags: COMPLETIONS.tags
|
||||
|
||||
# Tell autocomplete to fuzzy filter the results of getSuggestions(). We are
|
||||
# still filtering by the first character of the prefix in this provider for
|
||||
# efficiency.
|
||||
filterSuggestions: true
|
||||
|
||||
getSuggestions: (request) ->
|
||||
completions = null
|
||||
scopes = request.scopeDescriptor.getScopesArray()
|
||||
isSass = hasScope(scopes, 'source.sass', true)
|
||||
|
||||
if @isCompletingValue(request)
|
||||
completions = @getPropertyValueCompletions(request)
|
||||
else if @isCompletingPseudoSelector(request)
|
||||
completions = @getPseudoSelectorCompletions(request)
|
||||
else
|
||||
if isSass and @isCompletingNameOrTag(request)
|
||||
completions = @getPropertyNameCompletions(request)
|
||||
.concat(@getTagCompletions(request))
|
||||
else if not isSass and @isCompletingName(request)
|
||||
completions = @getPropertyNameCompletions(request)
|
||||
|
||||
if not isSass and @isCompletingTagSelector(request)
|
||||
tagCompletions = @getTagCompletions(request)
|
||||
if tagCompletions?.length
|
||||
completions ?= []
|
||||
completions = completions.concat(tagCompletions)
|
||||
|
||||
completions
|
||||
|
||||
onDidInsertSuggestion: ({editor, suggestion}) ->
|
||||
setTimeout(@triggerAutocomplete.bind(this, editor), 1) if suggestion.type is 'property'
|
||||
|
||||
triggerAutocomplete: (editor) ->
|
||||
atom.commands.dispatch(atom.views.getView(editor), 'autocomplete-plus:activate', {activatedManually: false})
|
||||
|
||||
isCompletingValue: ({scopeDescriptor, bufferPosition, prefix, editor}) ->
|
||||
scopes = scopeDescriptor.getScopesArray()
|
||||
|
||||
beforePrefixBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - prefix.length - 1)]
|
||||
beforePrefixScopes = editor.scopeDescriptorForBufferPosition(beforePrefixBufferPosition)
|
||||
beforePrefixScopesArray = beforePrefixScopes.getScopesArray()
|
||||
|
||||
previousBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - 1)]
|
||||
previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
|
||||
previousScopesArray = previousScopes.getScopesArray()
|
||||
|
||||
(hasScope(scopes, 'meta.property-list.css') and prefix.trim() is ":") or
|
||||
(hasScope(previousScopesArray, 'meta.property-value.css')) or
|
||||
(hasScope(scopes, 'meta.property-list.scss') and prefix.trim() is ":") or
|
||||
(hasScope(previousScopesArray, 'meta.property-value.scss')) or
|
||||
(hasScope(scopes, 'meta.property-list.postcss') and prefix.trim() is ":") or
|
||||
(hasScope(previousScopesArray, 'meta.property-value.postcss')) or
|
||||
(hasScope(scopes, 'source.sass', true) and (hasScope(scopes, 'meta.property-value.sass') or
|
||||
(not hasScope(beforePrefixScopesArray, 'entity.name.tag.css') and prefix.trim() is ":")
|
||||
))
|
||||
|
||||
isCompletingName: ({scopeDescriptor, bufferPosition, prefix, editor}) ->
|
||||
scopes = scopeDescriptor.getScopesArray()
|
||||
isAtTerminator = prefix.endsWith(';')
|
||||
isAtParentSymbol = prefix.endsWith('&')
|
||||
isVariable = hasScope(scopes, 'variable.css') or
|
||||
hasScope(scopes, 'variable.scss') or
|
||||
hasScope(scopes, 'variable.var.postcss')
|
||||
isInPropertyList = not isAtTerminator and
|
||||
(hasScope(scopes, 'meta.property-list.css') or
|
||||
hasScope(scopes, 'meta.property-list.scss') or
|
||||
hasScope(scopes, 'meta.property-list.postcss'))
|
||||
|
||||
return false unless isInPropertyList
|
||||
return false if isAtParentSymbol or isVariable
|
||||
|
||||
previousBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - prefix.length - 1)]
|
||||
previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
|
||||
previousScopesArray = previousScopes.getScopesArray()
|
||||
|
||||
return false if hasScope(previousScopesArray, 'entity.other.attribute-name.class.css') or
|
||||
hasScope(previousScopesArray, 'entity.other.attribute-name.id.css') or
|
||||
hasScope(previousScopesArray, 'entity.other.attribute-name.id') or
|
||||
hasScope(previousScopesArray, 'entity.other.attribute-name.parent-selector.css') or
|
||||
hasScope(previousScopesArray, 'entity.name.tag.reference.scss') or
|
||||
hasScope(previousScopesArray, 'entity.name.tag.scss') or
|
||||
hasScope(previousScopesArray, 'entity.name.tag.reference.postcss') or
|
||||
hasScope(previousScopesArray, 'entity.name.tag.postcss')
|
||||
|
||||
isAtBeginScopePunctuation = hasScope(scopes, 'punctuation.section.property-list.begin.bracket.curly.css') or
|
||||
hasScope(scopes, 'punctuation.section.property-list.begin.bracket.curly.scss') or
|
||||
hasScope(scopes, 'punctuation.section.property-list.begin.postcss')
|
||||
isAtEndScopePunctuation = hasScope(scopes, 'punctuation.section.property-list.end.bracket.curly.css') or
|
||||
hasScope(scopes, 'punctuation.section.property-list.end.bracket.curly.scss') or
|
||||
hasScope(scopes, 'punctuation.section.property-list.end.postcss')
|
||||
|
||||
if isAtBeginScopePunctuation
|
||||
# * Disallow here: `canvas,|{}`
|
||||
# * Allow here: `canvas,{| }`
|
||||
prefix.endsWith('{')
|
||||
else if isAtEndScopePunctuation
|
||||
# * Disallow here: `canvas,{}|`
|
||||
# * Allow here: `canvas,{ |}`
|
||||
not prefix.endsWith('}')
|
||||
else
|
||||
true
|
||||
|
||||
isCompletingNameOrTag: ({scopeDescriptor, bufferPosition, editor}) ->
|
||||
scopes = scopeDescriptor.getScopesArray()
|
||||
prefix = @getPropertyNamePrefix(bufferPosition, editor)
|
||||
return @isPropertyNamePrefix(prefix) and
|
||||
hasScope(scopes, 'meta.selector.css') and
|
||||
not hasScope(scopes, 'entity.other.attribute-name.id.css.sass') and
|
||||
not hasScope(scopes, 'entity.other.attribute-name.class.sass')
|
||||
|
||||
isCompletingTagSelector: ({editor, scopeDescriptor, bufferPosition}) ->
|
||||
scopes = scopeDescriptor.getScopesArray()
|
||||
tagSelectorPrefix = @getTagSelectorPrefix(editor, bufferPosition)
|
||||
return false unless tagSelectorPrefix?.length
|
||||
|
||||
previousBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - 1)]
|
||||
previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
|
||||
previousScopesArray = previousScopes.getScopesArray()
|
||||
|
||||
if hasScope(scopes, 'meta.selector.css') or hasScope(previousScopesArray, 'meta.selector.css')
|
||||
true
|
||||
else if hasScope(scopes, 'source.css.scss', true) or hasScope(scopes, 'source.css.less', true) or hasScope(scopes, 'source.css.postcss', true)
|
||||
not hasScope(previousScopesArray, 'meta.property-value.scss') and
|
||||
not hasScope(previousScopesArray, 'meta.property-value.css') and
|
||||
not hasScope(previousScopesArray, 'meta.property-value.postcss') and
|
||||
not hasScope(previousScopesArray, 'support.type.property-value.css')
|
||||
else
|
||||
false
|
||||
|
||||
isCompletingPseudoSelector: ({editor, scopeDescriptor, bufferPosition}) ->
|
||||
scopes = scopeDescriptor.getScopesArray()
|
||||
previousBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - 1)]
|
||||
previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
|
||||
previousScopesArray = previousScopes.getScopesArray()
|
||||
if (hasScope(scopes, 'meta.selector.css') or hasScope(previousScopesArray, 'meta.selector.css')) and not hasScope(scopes, 'source.sass', true)
|
||||
true
|
||||
else if hasScope(scopes, 'source.css.scss', true) or hasScope(scopes, 'source.css.less', true) or hasScope(scopes, 'source.sass', true) or hasScope(scopes, 'source.css.postcss', true)
|
||||
prefix = @getPseudoSelectorPrefix(editor, bufferPosition)
|
||||
if prefix
|
||||
previousBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - prefix.length - 1)]
|
||||
previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
|
||||
previousScopesArray = previousScopes.getScopesArray()
|
||||
not hasScope(previousScopesArray, 'meta.property-name.scss') and
|
||||
not hasScope(previousScopesArray, 'meta.property-value.scss') and
|
||||
not hasScope(previousScopesArray, 'meta.property-value.postcss') and
|
||||
not hasScope(previousScopesArray, 'support.type.property-name.css') and
|
||||
not hasScope(previousScopesArray, 'support.type.property-value.css') and
|
||||
not hasScope(previousScopesArray, 'support.type.property-name.postcss')
|
||||
else
|
||||
false
|
||||
else
|
||||
false
|
||||
|
||||
isPropertyValuePrefix: (prefix) ->
|
||||
prefix = prefix.trim()
|
||||
prefix.length > 0 and prefix isnt ':'
|
||||
|
||||
isPropertyNamePrefix: (prefix) ->
|
||||
return false unless prefix?
|
||||
prefix = prefix.trim()
|
||||
prefix.length > 0 and prefix.match(/^[a-zA-Z-]+$/)
|
||||
|
||||
getImportantPrefix: (editor, bufferPosition) ->
|
||||
line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
|
||||
importantPrefixPattern.exec(line)?[1]
|
||||
|
||||
getPreviousPropertyName: (bufferPosition, editor) ->
|
||||
{row, column} = bufferPosition
|
||||
while row >= 0
|
||||
line = editor.lineTextForBufferRow(row)
|
||||
line = line.substr(0, column) if row is bufferPosition.row
|
||||
propertyName = inlinePropertyNameWithColonPattern.exec(line)?[1]
|
||||
propertyName ?= firstInlinePropertyNameWithColonPattern.exec(line)?[1]
|
||||
propertyName ?= propertyNameWithColonPattern.exec(line)?[1]
|
||||
return propertyName if propertyName
|
||||
row--
|
||||
return
|
||||
|
||||
getPropertyValueCompletions: ({bufferPosition, editor, prefix, scopeDescriptor}) ->
|
||||
property = @getPreviousPropertyName(bufferPosition, editor)
|
||||
values = @properties[property]?.values
|
||||
return null unless values?
|
||||
|
||||
scopes = scopeDescriptor.getScopesArray()
|
||||
addSemicolon = not lineEndsWithSemicolon(bufferPosition, editor) and not hasScope(scopes, 'source.sass', true)
|
||||
|
||||
completions = []
|
||||
if @isPropertyValuePrefix(prefix)
|
||||
for value in values when firstCharsEqual(value, prefix)
|
||||
completions.push(@buildPropertyValueCompletion(value, property, addSemicolon))
|
||||
else if not hasScope(scopes, 'keyword.other.unit.percentage.css') and # CSS
|
||||
not hasScope(scopes, 'keyword.other.unit.scss') and # SCSS (TODO: remove in Atom 1.19.0)
|
||||
not hasScope(scopes, 'keyword.other.unit.css') # Less, Sass (TODO: remove in Atom 1.19.0)
|
||||
# Don't complete here: `width: 100%|`
|
||||
for value in values
|
||||
completions.push(@buildPropertyValueCompletion(value, property, addSemicolon))
|
||||
|
||||
if importantPrefix = @getImportantPrefix(editor, bufferPosition)
|
||||
# attention: règle dangereux
|
||||
completions.push
|
||||
type: 'keyword'
|
||||
text: '!important'
|
||||
displayText: '!important'
|
||||
replacementPrefix: importantPrefix
|
||||
description: "Forces this property to override any other declaration of the same property. Use with caution."
|
||||
descriptionMoreURL: "#{cssDocsURL}/Specificity#The_!important_exception"
|
||||
|
||||
completions
|
||||
|
||||
buildPropertyValueCompletion: (value, propertyName, addSemicolon) ->
|
||||
text = value
|
||||
text += ';' if addSemicolon
|
||||
|
||||
{
|
||||
type: 'value'
|
||||
text: text
|
||||
displayText: value
|
||||
description: "#{value} value for the #{propertyName} property"
|
||||
descriptionMoreURL: "#{cssDocsURL}/#{propertyName}#Values"
|
||||
}
|
||||
|
||||
getPropertyNamePrefix: (bufferPosition, editor) ->
|
||||
line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
|
||||
propertyNamePrefixPattern.exec(line)?[0]
|
||||
|
||||
getPropertyNameCompletions: ({bufferPosition, editor, scopeDescriptor, activatedManually}) ->
|
||||
# Don't autocomplete property names in SASS on root level
|
||||
scopes = scopeDescriptor.getScopesArray()
|
||||
line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
|
||||
return [] if hasScope(scopes, 'source.sass', true) and not line.match(/^(\s|\t)/)
|
||||
|
||||
prefix = @getPropertyNamePrefix(bufferPosition, editor)
|
||||
return [] unless activatedManually or prefix
|
||||
|
||||
completions = []
|
||||
for property, options of @properties when not prefix or firstCharsEqual(property, prefix)
|
||||
completions.push(@buildPropertyNameCompletion(property, prefix, options))
|
||||
completions
|
||||
|
||||
buildPropertyNameCompletion: (propertyName, prefix, {description}) ->
|
||||
type: 'property'
|
||||
text: "#{propertyName}: "
|
||||
displayText: propertyName
|
||||
replacementPrefix: prefix
|
||||
description: description
|
||||
descriptionMoreURL: "#{cssDocsURL}/#{propertyName}"
|
||||
|
||||
getPseudoSelectorPrefix: (editor, bufferPosition) ->
|
||||
line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
|
||||
line.match(pseudoSelectorPrefixPattern)?[0]
|
||||
|
||||
getPseudoSelectorCompletions: ({bufferPosition, editor}) ->
|
||||
prefix = @getPseudoSelectorPrefix(editor, bufferPosition)
|
||||
return null unless prefix
|
||||
|
||||
completions = []
|
||||
for pseudoSelector, options of @pseudoSelectors when firstCharsEqual(pseudoSelector, prefix)
|
||||
completions.push(@buildPseudoSelectorCompletion(pseudoSelector, prefix, options))
|
||||
completions
|
||||
|
||||
buildPseudoSelectorCompletion: (pseudoSelector, prefix, {argument, description}) ->
|
||||
completion =
|
||||
type: 'pseudo-selector'
|
||||
replacementPrefix: prefix
|
||||
description: description
|
||||
descriptionMoreURL: "#{cssDocsURL}/#{pseudoSelector}"
|
||||
|
||||
if argument?
|
||||
completion.snippet = "#{pseudoSelector}(${1:#{argument}})"
|
||||
else
|
||||
completion.text = pseudoSelector
|
||||
completion
|
||||
|
||||
getTagSelectorPrefix: (editor, bufferPosition) ->
|
||||
line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
|
||||
tagSelectorPrefixPattern.exec(line)?[2]
|
||||
|
||||
getTagCompletions: ({bufferPosition, editor, prefix}) ->
|
||||
completions = []
|
||||
if prefix
|
||||
for tag in @tags when firstCharsEqual(tag, prefix)
|
||||
completions.push(@buildTagCompletion(tag))
|
||||
completions
|
||||
|
||||
buildTagCompletion: (tag) ->
|
||||
type: 'tag'
|
||||
text: tag
|
||||
description: "Selector for <#{tag}> elements"
|
||||
|
||||
lineEndsWithSemicolon = (bufferPosition, editor) ->
|
||||
{row} = bufferPosition
|
||||
line = editor.lineTextForBufferRow(row)
|
||||
/;\s*$/.test(line)
|
||||
|
||||
hasScope = (scopesArray, scope, checkEmbedded = false) ->
|
||||
scopesArray.indexOf(scope) isnt -1 or
|
||||
(checkEmbedded and scopesArray.indexOf("#{scope}.embedded.html") isnt -1)
|
||||
|
||||
firstCharsEqual = (str1, str2) ->
|
||||
str1[0].toLowerCase() is str2[0].toLowerCase()
|
873
packages/autocomplete-css/package-lock.json
generated
Normal file
873
packages/autocomplete-css/package-lock.json
generated
Normal file
@ -0,0 +1,873 @@
|
||||
{
|
||||
"name": "autocomplete-css",
|
||||
"version": "0.17.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "autocomplete-css",
|
||||
"version": "0.17.5",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"request": "^2.53.0"
|
||||
},
|
||||
"engines": {
|
||||
"atom": ">=0.174.0 <2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/aws4": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"node_modules/caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
|
||||
"dev": true,
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
]
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/har-validator": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"deprecated": "this library is no longer supported",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8",
|
||||
"npm": ">=1.3.7"
|
||||
}
|
||||
},
|
||||
"node_modules/is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-schema": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
|
||||
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jsprim": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
|
||||
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.4.0",
|
||||
"verror": "1.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/psl": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
|
||||
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/request": {
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sshpk": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
|
||||
"integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
},
|
||||
"bin": {
|
||||
"sshpk-conv": "bin/sshpk-conv",
|
||||
"sshpk-sign": "bin/sshpk-sign",
|
||||
"sshpk-verify": "bin/sshpk-verify"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"uuid": "bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
|
||||
"dev": true,
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
],
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||
"dev": true
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
|
||||
"dev": true
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
|
||||
"dev": true
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
|
||||
"dev": true
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
|
||||
"dev": true
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"dev": true
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
|
||||
"dev": true
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
|
||||
"dev": true
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
|
||||
"dev": true
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
|
||||
"dev": true
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
|
||||
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
|
||||
"dev": true
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
|
||||
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.4.0",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
||||
"dev": true
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
|
||||
"dev": true
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"dev": true
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
|
||||
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
|
||||
"dev": true
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
|
||||
"integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
|
||||
"dev": true
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"dev": true
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
packages/autocomplete-css/package.json
Normal file
21
packages/autocomplete-css/package.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "autocomplete-css",
|
||||
"version": "0.17.5",
|
||||
"description": "CSS property name and value autocompletions",
|
||||
"main": "./lib/main",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/pulsar-edit/pulsar",
|
||||
"engines": {
|
||||
"atom": ">=0.174.0 <2.0.0"
|
||||
},
|
||||
"providedServices": {
|
||||
"autocomplete.provider": {
|
||||
"versions": {
|
||||
"2.0.0": "getProvider"
|
||||
}
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"request": "^2.53.0"
|
||||
}
|
||||
}
|
138
packages/autocomplete-css/pseudo-selectors.json
Normal file
138
packages/autocomplete-css/pseudo-selectors.json
Normal file
@ -0,0 +1,138 @@
|
||||
{
|
||||
"::after": {
|
||||
"description": "Matches a virtual last child of the selected element."
|
||||
},
|
||||
"::before": {
|
||||
"description": "Creates a pseudo-element that is the first child of the element matched."
|
||||
},
|
||||
"::first-letter": {
|
||||
"description": "Matches the first letter of the first line of a block, if it is not preceded by any other content."
|
||||
},
|
||||
"::first-line": {
|
||||
"description": "Applies styles only to the first line of an element."
|
||||
},
|
||||
"::selection": {
|
||||
"description": "Applies rules to the portion of a document that has been highlighted."
|
||||
},
|
||||
":active": {
|
||||
"description": "Matches when an element is being activated by the user."
|
||||
},
|
||||
":checked": {
|
||||
"description": "Matches any radio input, checkbox input or option element that is checked or toggled to an on state."
|
||||
},
|
||||
":default": {
|
||||
"description": "Matches any user interface element that is the default among a group of similar elements"
|
||||
},
|
||||
":dir": {
|
||||
"argument": "direction",
|
||||
"description": "Matches elements based on the directionality of the text contained in it."
|
||||
},
|
||||
":disabled": {
|
||||
"description": "Matches any disabled element."
|
||||
},
|
||||
":empty": {
|
||||
"description": "Matches any element that has no children at all."
|
||||
},
|
||||
":enabled": {
|
||||
"description": "Matches any enabled element."
|
||||
},
|
||||
":first": {
|
||||
"description": "Describes the styling of the first page when printing a document."
|
||||
},
|
||||
":first-child": {
|
||||
"description": "Matches any element that is the first child element of its parent."
|
||||
},
|
||||
":first-of-type": {
|
||||
"description": "Matches the first sibling of its type in the list of children of its parent element."
|
||||
},
|
||||
":focus": {
|
||||
"description": "Matches an element that has focus."
|
||||
},
|
||||
":fullscreen": {
|
||||
"description": "Applies to any element that's currently being displayed in full-screen mode."
|
||||
},
|
||||
":hover": {
|
||||
"description": "Matches when the user designates an element with a pointing device, but does not necessarily activate it."
|
||||
},
|
||||
":indeterminate": {
|
||||
"description": "Matches any checkbox input whose indeterminate DOM property is set to true by JavaScript."
|
||||
},
|
||||
":invalid": {
|
||||
"description": "Matches any <input> or <form> element whose content fails to validate according to the input's type setting."
|
||||
},
|
||||
":lang": {
|
||||
"argument": "language",
|
||||
"description": "Matches elements based on the language the element is determined to be in."
|
||||
},
|
||||
":last-child": {
|
||||
"description": "Matches any element that is the last child element of its parent."
|
||||
},
|
||||
":last-of-type": {
|
||||
"description": "Matches the last sibling with the given element name in the list of children of its parent element."
|
||||
},
|
||||
":left": {
|
||||
"description": "Matches any left page when printing a page."
|
||||
},
|
||||
":link": {
|
||||
"description": "Matches links inside elements."
|
||||
},
|
||||
":not": {
|
||||
"argument": "selector",
|
||||
"description": "Matches an element that is not represented by the argument."
|
||||
},
|
||||
":nth-child": {
|
||||
"argument": "an+b",
|
||||
"description": "Matches an element that has an+b-1 siblings before it in the document tree."
|
||||
},
|
||||
":nth-last-child": {
|
||||
"argument": "an+b",
|
||||
"description": "Matches an element that has an+b-1 siblings after it in the document tree."
|
||||
},
|
||||
":nth-last-of-type": {
|
||||
"argument": "an+b",
|
||||
"description": "Matches an element that has an+b-1 siblings with the same element name after it in the document tree."
|
||||
},
|
||||
":nth-of-type": {
|
||||
"argument": "an+b",
|
||||
"description": "Matches an element that has an+b-1 siblings with the same element name before it in the document tree"
|
||||
},
|
||||
":only-child": {
|
||||
"description": "Matches any element which is the only child of its parent."
|
||||
},
|
||||
":only-of-type": {
|
||||
"description": "Matches any element that has no siblings of the given type."
|
||||
},
|
||||
":optional": {
|
||||
"description": "Matches any <input> element that does not have the required attribute set on it."
|
||||
},
|
||||
":out-of-range": {
|
||||
"description": "Matches when an element has its value attribute outside the specified range limitations for this element."
|
||||
},
|
||||
":read-only": {
|
||||
"description": "Matches when an element is not writable by the user."
|
||||
},
|
||||
":read-write": {
|
||||
"description": "Matches when an element is editable by user like text input element."
|
||||
},
|
||||
":required": {
|
||||
"description": "Matches any <input> element that has the required attribute set on it."
|
||||
},
|
||||
":right": {
|
||||
"description": "Matches any right page when printing a page. It allows to describe the styling of right-side page."
|
||||
},
|
||||
":root": {
|
||||
"description": "Matches the root element of a tree representing the document."
|
||||
},
|
||||
":scope": {
|
||||
"description": "Matches the elements that are a reference point for selectors to match against."
|
||||
},
|
||||
":target": {
|
||||
"description": "Matches the unique element, if any, with an id matching the fragment identifier of the URI of the document."
|
||||
},
|
||||
":valid": {
|
||||
"description": "Matches any <input> or <form> element whose content validates correctly according to the input's type setting"
|
||||
},
|
||||
":visited": {
|
||||
"description": "Matches links that have been visited."
|
||||
}
|
||||
}
|
462
packages/autocomplete-css/sorted-property-names.json
Normal file
462
packages/autocomplete-css/sorted-property-names.json
Normal file
@ -0,0 +1,462 @@
|
||||
[
|
||||
"width",
|
||||
"height",
|
||||
"margin",
|
||||
"margin-left",
|
||||
"margin-right",
|
||||
"margin-top",
|
||||
"margin-bottom",
|
||||
"padding",
|
||||
"padding-left",
|
||||
"padding-right",
|
||||
"padding-top",
|
||||
"padding-bottom",
|
||||
"font",
|
||||
"font-size",
|
||||
"font-style",
|
||||
"font-weight",
|
||||
"font-family",
|
||||
"border",
|
||||
"border-radius",
|
||||
"border-top",
|
||||
"border-bottom",
|
||||
"border-left",
|
||||
"border-right",
|
||||
"border-color",
|
||||
"border-width",
|
||||
"position",
|
||||
"text-align",
|
||||
"background",
|
||||
"background-color",
|
||||
"background-position",
|
||||
"background-repeat",
|
||||
"background-image",
|
||||
"background-size",
|
||||
"background-clip",
|
||||
"right",
|
||||
"left",
|
||||
"top",
|
||||
"bottom",
|
||||
"overflow",
|
||||
"overflow-x",
|
||||
"overflow-y",
|
||||
"opacity",
|
||||
"cursor",
|
||||
"display",
|
||||
"color",
|
||||
"visibility",
|
||||
"float",
|
||||
"text-decoration",
|
||||
"line-height",
|
||||
"z-index",
|
||||
"vertical-align",
|
||||
"box-sizing",
|
||||
"clear",
|
||||
"white-space",
|
||||
"max-width",
|
||||
"outline",
|
||||
"content",
|
||||
"min-width",
|
||||
"min-height",
|
||||
"list-style",
|
||||
"box-shadow",
|
||||
"webkit-border-radius",
|
||||
"webkit-user-select",
|
||||
"webkit-box-shadow",
|
||||
"text-shadow",
|
||||
"text-indent",
|
||||
"max-height",
|
||||
"text-overflow",
|
||||
"border-style",
|
||||
"border-spacing",
|
||||
"border-collapse",
|
||||
"border-left-color",
|
||||
"border-left-style",
|
||||
"border-left-width",
|
||||
"border-right-color",
|
||||
"border-right-style",
|
||||
"border-right-width",
|
||||
"border-top-color",
|
||||
"border-top-style",
|
||||
"border-top-width",
|
||||
"border-bottom-color",
|
||||
"border-bottom-style",
|
||||
"border-bottom-width",
|
||||
"border-top-left-radius",
|
||||
"border-top-right-radius",
|
||||
"border-bottom-left-radius",
|
||||
"border-bottom-right-radius",
|
||||
"user-select",
|
||||
"text-transform",
|
||||
"webkit-transition",
|
||||
"zoom",
|
||||
"list-style-type",
|
||||
"word-wrap",
|
||||
"webkit-transform",
|
||||
"transition",
|
||||
"webkit-appearance",
|
||||
"letter-spacing",
|
||||
"transform",
|
||||
"pointer-events",
|
||||
"webkit-font-smoothing",
|
||||
"webkit-animation",
|
||||
"direction",
|
||||
"clip",
|
||||
"table-layout",
|
||||
"src",
|
||||
"webkit-tap-highlight-color",
|
||||
"resize",
|
||||
"webkit-transform-origin",
|
||||
"word-break",
|
||||
"webkit-background-clip",
|
||||
"webkit-background-size",
|
||||
"filter",
|
||||
"transform-origin",
|
||||
"font-variant",
|
||||
"webkit-filter",
|
||||
"quotes",
|
||||
"unicode-bidi",
|
||||
"word-spacing",
|
||||
"text-rendering",
|
||||
"fill",
|
||||
"webkit-backface-visibility",
|
||||
"webkit-transition-duration",
|
||||
"outline-color",
|
||||
"list-style-position",
|
||||
"webkit-box-orient",
|
||||
"webkit-animation-timing-function",
|
||||
"outline-offset",
|
||||
"webkit-transition-property",
|
||||
"webkit-animation-duration",
|
||||
"webkit-animation-name",
|
||||
"orphans",
|
||||
"outline-style",
|
||||
"outline-width",
|
||||
"flex",
|
||||
"flex-grow",
|
||||
"flex-direction",
|
||||
"flex-flow",
|
||||
"flex-wrap",
|
||||
"flex-shrink",
|
||||
"flex-basis",
|
||||
"list-style-image",
|
||||
"unicode-range",
|
||||
"align-items",
|
||||
"transition-delay",
|
||||
"webkit-animation-fill-mode",
|
||||
"transition-duration",
|
||||
"justify-content",
|
||||
"transition-property",
|
||||
"webkit-animation-iteration-count",
|
||||
"webkit-line-clamp",
|
||||
"webkit-transition-timing-function",
|
||||
"order",
|
||||
"transition-timing-function",
|
||||
"background-attachment",
|
||||
"background-position-y",
|
||||
"background-origin",
|
||||
"background-position-x",
|
||||
"backface-visibility",
|
||||
"page-break-inside",
|
||||
"page-break-after",
|
||||
"speak",
|
||||
"stroke",
|
||||
"webkit-box-flex",
|
||||
"webkit-transition-delay",
|
||||
"widows",
|
||||
"webkit-perspective",
|
||||
"stroke-width",
|
||||
"webkit-animation-direction",
|
||||
"fill-opacity",
|
||||
"webkit-box-pack",
|
||||
"webkit-user-drag",
|
||||
"overflow-wrap",
|
||||
"webkit-box-align",
|
||||
"webkit-animation-play-state",
|
||||
"counter-increment",
|
||||
"counter-reset",
|
||||
"webkit-animation-delay",
|
||||
"image-rendering",
|
||||
"perspective-origin",
|
||||
"webkit-perspective-origin",
|
||||
"perspective",
|
||||
"webkit-margin-start",
|
||||
"webkit-transform-style",
|
||||
"empty-cells",
|
||||
"stroke-opacity",
|
||||
"caption-side",
|
||||
"webkit-mask-image",
|
||||
"webkit-margin-end",
|
||||
"transform-style",
|
||||
"border-image",
|
||||
"touch-action",
|
||||
"webkit-box-ordinal-group",
|
||||
"webkit-column-count",
|
||||
"font-stretch",
|
||||
"webkit-print-color-adjust",
|
||||
"webkit-mask-size",
|
||||
"webkit-column-gap",
|
||||
"webkit-margin-top-collapse",
|
||||
"webkit-border-image",
|
||||
"will-change",
|
||||
"webkit-padding-start",
|
||||
"webkit-mask-repeat",
|
||||
"webkit-text-fill-color",
|
||||
"webkit-margin-before",
|
||||
"webkit-mask-box-image",
|
||||
"webkit-border-horizontal-spacing",
|
||||
"animation",
|
||||
"webkit-column-break-inside",
|
||||
"page-break-before",
|
||||
"webkit-margin-after",
|
||||
"webkit-user-modify",
|
||||
"webkit-font-feature-settings",
|
||||
"webkit-line-break",
|
||||
"webkit-mask-position",
|
||||
"align-self",
|
||||
"webkit-box-direction",
|
||||
"size",
|
||||
"align-content",
|
||||
"webkit-text-stroke",
|
||||
"webkit-padding-end",
|
||||
"webkit-text-stroke-width",
|
||||
"border-image-slice",
|
||||
"border-image-width",
|
||||
"webkit-column-width",
|
||||
"border-image-outset",
|
||||
"webkit-columns",
|
||||
"border-image-repeat",
|
||||
"tab-size",
|
||||
"stop-color",
|
||||
"object-fit",
|
||||
"fill-rule",
|
||||
"writing-mode",
|
||||
"clip-rule",
|
||||
"shape-rendering",
|
||||
"stroke-dasharray",
|
||||
"webkit-text-stroke-color",
|
||||
"font-kerning",
|
||||
"webkit-background-origin",
|
||||
"stroke-linecap",
|
||||
"webkit-box-reflect",
|
||||
"animation-name",
|
||||
"text-anchor",
|
||||
"animation-duration",
|
||||
"stop-opacity",
|
||||
"webkit-border-vertical-spacing",
|
||||
"webkit-perspective-origin-y",
|
||||
"border-image-source",
|
||||
"stroke-linejoin",
|
||||
"webkit-perspective-origin-x",
|
||||
"animation-fill-mode",
|
||||
"webkit-padding-before",
|
||||
"webkit-column-rule-color",
|
||||
"webkit-column-span",
|
||||
"webkit-column-rule",
|
||||
"animation-timing-function",
|
||||
"mask",
|
||||
"webkit-mask",
|
||||
"stroke-miterlimit",
|
||||
"webkit-text-security",
|
||||
"webkit-box-lines",
|
||||
"webkit-padding-after",
|
||||
"webkit-border-end",
|
||||
"webkit-text-emphasis-color",
|
||||
"webkit-border-start-color",
|
||||
"webkit-border-start-width",
|
||||
"animation-iteration-count",
|
||||
"stroke-dashoffset",
|
||||
"animation-delay",
|
||||
"webkit-rtl-ordering",
|
||||
"page",
|
||||
"webkit-margin-collapse",
|
||||
"webkit-border-start",
|
||||
"webkit-transform-origin-y",
|
||||
"webkit-writing-mode",
|
||||
"alignment-baseline",
|
||||
"dominant-baseline",
|
||||
"webkit-column-rule-style",
|
||||
"webkit-column-rule-width",
|
||||
"baseline-shift",
|
||||
"webkit-highlight",
|
||||
"font-variant-ligatures",
|
||||
"webkit-transform-origin-x",
|
||||
"webkit-app-region",
|
||||
"webkit-clip-path",
|
||||
"background-blend-mode",
|
||||
"clip-path",
|
||||
"object-position",
|
||||
"webkit-box-decoration-break",
|
||||
"x",
|
||||
"webkit-border-end-color",
|
||||
"enable-background",
|
||||
"webkit-hyphenate-character",
|
||||
"mask-type",
|
||||
"webkit-column-break-before",
|
||||
"webkit-column-break-after",
|
||||
"mix-blend-mode",
|
||||
"webkit-text-decorations-in-effect",
|
||||
"webkit-box-flex-group",
|
||||
"webkit-line-box-contain",
|
||||
"webkit-mask-composite",
|
||||
"vector-effect",
|
||||
"marker-start",
|
||||
"marker-end",
|
||||
"webkit-border-end-width",
|
||||
"webkit-mask-clip",
|
||||
"flood-color",
|
||||
"flood-opacity",
|
||||
"webkit-background-composite",
|
||||
"marker-mid",
|
||||
"webkit-mask-origin",
|
||||
"webkit-text-emphasis-style",
|
||||
"color-rendering",
|
||||
"color-interpolation-filters",
|
||||
"webkit-margin-before-collapse",
|
||||
"color-interpolation",
|
||||
"webkit-border-after-color",
|
||||
"webkit-border-before-color",
|
||||
"webkit-text-orientation",
|
||||
"webkit-border-after-width",
|
||||
"background-repeat-y",
|
||||
"webkit-border-before-width",
|
||||
"glyph-orientation-vertical",
|
||||
"lighting-color",
|
||||
"glyph-orientation-horizontal",
|
||||
"webkit-mask-box-image-source",
|
||||
"webkit-mask-box-image-repeat",
|
||||
"shape-outside",
|
||||
"webkit-mask-box-image-slice",
|
||||
"paint-order",
|
||||
"webkit-text-combine",
|
||||
"webkit-text-emphasis-position",
|
||||
"shape-margin",
|
||||
"webkit-mask-box-image-width",
|
||||
"webkit-mask-box-image-outset",
|
||||
"webkit-margin-after-collapse",
|
||||
"isolation",
|
||||
"buffered-rendering",
|
||||
"shape-image-threshold",
|
||||
"background-repeat-x",
|
||||
"animation-direction",
|
||||
"animation-play-state",
|
||||
"webkit-locale",
|
||||
"webkit-border-end-style",
|
||||
"webkit-margin-bottom-collapse",
|
||||
"all",
|
||||
"marker",
|
||||
"webkit-border-after",
|
||||
"y",
|
||||
"rx",
|
||||
"ry",
|
||||
"cx",
|
||||
"cy",
|
||||
"r",
|
||||
"webkit-border-start-style",
|
||||
"webkit-mask-position-x",
|
||||
"webkit-border-fit",
|
||||
"webkit-transform-origin-z",
|
||||
"text-justify",
|
||||
"column-fill",
|
||||
"text-align-last",
|
||||
"webkit-min-logical-height",
|
||||
"text-decoration-color",
|
||||
"webkit-min-logical-width",
|
||||
"webkit-logical-height",
|
||||
"text-decoration-style",
|
||||
"text-decoration-line",
|
||||
"webkit-mask-position-y",
|
||||
"min-zoom",
|
||||
"max-zoom",
|
||||
"webkit-max-logical-height",
|
||||
"webkit-border-before",
|
||||
"webkit-text-emphasis",
|
||||
"webkit-max-logical-width",
|
||||
"webkit-logical-width",
|
||||
"user-zoom",
|
||||
"webkit-border-after-style",
|
||||
"font-size-adjust",
|
||||
"text-underline-style",
|
||||
"orientation",
|
||||
"webkit-font-size-delta",
|
||||
"text-underline-position",
|
||||
"webkit-border-before-style",
|
||||
"text-underline-color",
|
||||
"touch-action-delay",
|
||||
"webkit-ruby-position",
|
||||
"webkit-mask-repeat-x",
|
||||
"webkit-mask-repeat-y",
|
||||
"scroll-behavior",
|
||||
"justify-self",
|
||||
"text-overline-width",
|
||||
"grid-column",
|
||||
"grid-row",
|
||||
"grid-template",
|
||||
"text-line-through-width",
|
||||
"caret-color",
|
||||
"justify-items",
|
||||
"grid-template-columns",
|
||||
"grid-auto-columns",
|
||||
"grid-auto-flow",
|
||||
"mask-source-type",
|
||||
"grid-auto-rows",
|
||||
"grid-column-start",
|
||||
"grid-template-rows",
|
||||
"scroll-blocks-on",
|
||||
"grid-row-end",
|
||||
"grid-column-end",
|
||||
"grid-row-start",
|
||||
"text-line-through-style",
|
||||
"text-line-through-mode",
|
||||
"webkit-wrap-flow",
|
||||
"webkit-wrap-through",
|
||||
"text-line-through-color",
|
||||
"text-overline-color",
|
||||
"webkit-aspect-ratio",
|
||||
"text-underline-width",
|
||||
"text-underline-mode",
|
||||
"box-decoration-break",
|
||||
"break-after",
|
||||
"break-before",
|
||||
"break-inside",
|
||||
"columns",
|
||||
"column-count",
|
||||
"column-gap",
|
||||
"column-rule",
|
||||
"column-rule-color",
|
||||
"column-rule-style",
|
||||
"column-rule-width",
|
||||
"column-span",
|
||||
"column-width",
|
||||
"flow-into",
|
||||
"flow-from",
|
||||
"font-feature-settings",
|
||||
"font-language-override",
|
||||
"font-synthesis",
|
||||
"font-variant-alternates",
|
||||
"font-variant-caps",
|
||||
"font-variant-east-asian",
|
||||
"font-variant-numeric",
|
||||
"font-variant-position",
|
||||
"hyphens",
|
||||
"image-orientation",
|
||||
"image-resolution",
|
||||
"region-break-after",
|
||||
"region-break-before",
|
||||
"region-break-inside",
|
||||
"region-fragment",
|
||||
"shape-inside",
|
||||
"text-decoration-skip",
|
||||
"text-emphasis",
|
||||
"text-emphasis-color",
|
||||
"text-emphasis-position",
|
||||
"text-emphasis-style",
|
||||
"font-display",
|
||||
"grid",
|
||||
"grid-area",
|
||||
"grid-column-gap",
|
||||
"grid-gap",
|
||||
"grid-row-gap",
|
||||
"grid-template-areas",
|
||||
"hanging-punctuation"
|
||||
]
|
907
packages/autocomplete-css/spec/provider-spec.coffee
Normal file
907
packages/autocomplete-css/spec/provider-spec.coffee
Normal file
@ -0,0 +1,907 @@
|
||||
packagesToTest =
|
||||
CSS:
|
||||
name: 'language-css'
|
||||
file: 'test.css'
|
||||
SCSS:
|
||||
name: 'language-sass'
|
||||
file: 'test.scss'
|
||||
Less:
|
||||
name: 'language-less'
|
||||
file: 'test.less'
|
||||
PostCSS:
|
||||
name: 'language-postcss'
|
||||
file: 'test.postcss'
|
||||
|
||||
Object.keys(packagesToTest).forEach (packageLabel) ->
|
||||
unless atom.packages.getAvailablePackageNames().includes(packagesToTest[packageLabel].name)
|
||||
console.warn "Skipping tests for #{packageLabel} because it is not installed"
|
||||
delete packagesToTest[packageLabel]
|
||||
|
||||
describe "CSS property name and value autocompletions", ->
|
||||
[editor, provider] = []
|
||||
|
||||
getCompletions = (options={}) ->
|
||||
cursor = editor.getLastCursor()
|
||||
start = cursor.getBeginningOfCurrentWordBufferPosition()
|
||||
end = cursor.getBufferPosition()
|
||||
prefix = editor.getTextInRange([start, end])
|
||||
request =
|
||||
editor: editor
|
||||
bufferPosition: end
|
||||
scopeDescriptor: cursor.getScopeDescriptor()
|
||||
prefix: prefix
|
||||
activatedManually: options.activatedManually ? true
|
||||
provider.getSuggestions(request)
|
||||
|
||||
beforeEach ->
|
||||
waitsForPromise -> atom.packages.activatePackage('autocomplete-css')
|
||||
waitsForPromise -> atom.packages.activatePackage('language-css') # Used in all CSS languages
|
||||
|
||||
runs ->
|
||||
provider = atom.packages.getActivePackage('autocomplete-css').mainModule.getProvider()
|
||||
|
||||
waitsFor -> Object.keys(provider.properties).length > 0
|
||||
|
||||
Object.keys(packagesToTest).forEach (packageLabel) ->
|
||||
describe "#{packageLabel} files", ->
|
||||
beforeEach ->
|
||||
waitsForPromise -> atom.packages.activatePackage(packagesToTest[packageLabel].name)
|
||||
waitsForPromise -> atom.workspace.open(packagesToTest[packageLabel].file)
|
||||
runs -> editor = atom.workspace.getActiveTextEditor()
|
||||
|
||||
it "returns tag completions when not in a property list", ->
|
||||
editor.setText('')
|
||||
expect(getCompletions()).toBe null
|
||||
|
||||
editor.setText('d')
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
expect(getCompletions()).toBe null
|
||||
|
||||
editor.setCursorBufferPosition([0, 1])
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 9
|
||||
for completion in completions
|
||||
expect(completion.text.length).toBeGreaterThan 0
|
||||
expect(completion.type).toBe 'tag'
|
||||
|
||||
it "autocompletes property names without a prefix when activated manually", ->
|
||||
editor.setText """
|
||||
body {
|
||||
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 0])
|
||||
completions = getCompletions(activatedManually: true)
|
||||
expect(completions.length).toBe 237
|
||||
for completion in completions
|
||||
expect(completion.text.length).toBeGreaterThan 0
|
||||
expect(completion.type).toBe 'property'
|
||||
expect(completion.descriptionMoreURL.length).toBeGreaterThan 0
|
||||
|
||||
it "does not autocomplete property names without a prefix when not activated manually", ->
|
||||
editor.setText """
|
||||
body {
|
||||
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 0])
|
||||
completions = getCompletions(activatedManually: false)
|
||||
expect(completions).toEqual []
|
||||
|
||||
it "autocompletes property names with a prefix", ->
|
||||
editor.setText """
|
||||
body {
|
||||
d
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].text).toBe 'display: '
|
||||
expect(completions[0].displayText).toBe 'display'
|
||||
expect(completions[0].type).toBe 'property'
|
||||
expect(completions[0].replacementPrefix).toBe 'd'
|
||||
expect(completions[0].description.length).toBeGreaterThan 0
|
||||
expect(completions[0].descriptionMoreURL.length).toBeGreaterThan 0
|
||||
expect(completions[1].text).toBe 'direction: '
|
||||
expect(completions[1].displayText).toBe 'direction'
|
||||
expect(completions[1].type).toBe 'property'
|
||||
expect(completions[1].replacementPrefix).toBe 'd'
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
D
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 2
|
||||
expect(completions[0].text).toBe 'display: '
|
||||
expect(completions[1].text).toBe 'direction: '
|
||||
expect(completions[1].replacementPrefix).toBe 'D'
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
d:
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].text).toBe 'display: '
|
||||
expect(completions[1].text).toBe 'direction: '
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
bord
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 6])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].text).toBe 'border: '
|
||||
expect(completions[0].displayText).toBe 'border'
|
||||
expect(completions[0].replacementPrefix).toBe 'bord'
|
||||
|
||||
it "does not autocomplete when at a terminator", ->
|
||||
editor.setText """
|
||||
body {
|
||||
.somemixin();
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 15])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
it "does not autocomplete property names when preceding a {", ->
|
||||
editor.setText """
|
||||
body,{
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
editor.setText """
|
||||
body,{}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
{
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 0])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
it "does not autocomplete property names when immediately after a }", ->
|
||||
editor.setText """
|
||||
body{}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
editor.setText """
|
||||
body{
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 1])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
it "autocompletes property names when the cursor is up against the punctuation inside the property list", ->
|
||||
editor.setText """
|
||||
body {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].displayText).toBe 'width'
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 0])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].displayText).toBe 'width'
|
||||
|
||||
editor.setText """
|
||||
body { }
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].displayText).toBe 'width'
|
||||
|
||||
editor.setText """
|
||||
body { }
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 7])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].displayText).toBe 'width'
|
||||
|
||||
it "triggers autocomplete when an property name has been inserted", ->
|
||||
spyOn(atom.commands, 'dispatch')
|
||||
suggestion = {type: 'property', text: 'whatever'}
|
||||
provider.onDidInsertSuggestion({editor, suggestion})
|
||||
|
||||
advanceClock 1
|
||||
expect(atom.commands.dispatch).toHaveBeenCalled()
|
||||
|
||||
args = atom.commands.dispatch.mostRecentCall.args
|
||||
expect(args[0].tagName.toLowerCase()).toBe 'atom-text-editor'
|
||||
expect(args[1]).toBe 'autocomplete-plus:activate'
|
||||
|
||||
it "autocompletes property values without a prefix", ->
|
||||
editor.setText """
|
||||
body {
|
||||
display:
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 10])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 24
|
||||
for completion in completions
|
||||
expect(completion.text.length).toBeGreaterThan 0
|
||||
expect(completion.description.length).toBeGreaterThan 0
|
||||
expect(completion.descriptionMoreURL.length).toBeGreaterThan 0
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
display:
|
||||
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([2, 0])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 24
|
||||
for completion in completions
|
||||
expect(completion.text.length).toBeGreaterThan 0
|
||||
|
||||
it "autocompletes property values with a prefix", ->
|
||||
editor.setText """
|
||||
body {
|
||||
display: i
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 12])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].text).toBe 'inline;'
|
||||
expect(completions[0].description.length).toBeGreaterThan 0
|
||||
expect(completions[0].descriptionMoreURL.length).toBeGreaterThan 0
|
||||
expect(completions[1].text).toBe 'inline-block;'
|
||||
expect(completions[2].text).toBe 'inline-flex;'
|
||||
expect(completions[3].text).toBe 'inline-grid;'
|
||||
expect(completions[4].text).toBe 'inline-table;'
|
||||
expect(completions[5].text).toBe 'inherit;'
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
display: I
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 12])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 6
|
||||
expect(completions[0].text).toBe 'inline;'
|
||||
expect(completions[1].text).toBe 'inline-block;'
|
||||
expect(completions[2].text).toBe 'inline-flex;'
|
||||
expect(completions[3].text).toBe 'inline-grid;'
|
||||
expect(completions[4].text).toBe 'inline-table;'
|
||||
expect(completions[5].text).toBe 'inherit;'
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
display:
|
||||
i
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([2, 5])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].text).toBe 'inline;'
|
||||
expect(completions[1].text).toBe 'inline-block;'
|
||||
expect(completions[2].text).toBe 'inline-flex;'
|
||||
expect(completions[3].text).toBe 'inline-grid;'
|
||||
expect(completions[4].text).toBe 'inline-table;'
|
||||
expect(completions[5].text).toBe 'inherit;'
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
text-align:
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 13])
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 5
|
||||
expect(completions[0].text).toBe 'center;'
|
||||
expect(completions[1].text).toBe 'left;'
|
||||
expect(completions[2].text).toBe 'justify;'
|
||||
expect(completions[3].text).toBe 'right;'
|
||||
expect(completions[4].text).toBe 'inherit;'
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
text-align: c
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 15])
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 1
|
||||
expect(completions[0].text).toBe 'center;'
|
||||
|
||||
it "does not complete property values after percentage signs", ->
|
||||
editor.setText """
|
||||
body {
|
||||
width: 100%
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 13])
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 0
|
||||
|
||||
it "it doesn't add semicolon after a property if one is already present", ->
|
||||
editor.setText """
|
||||
body {
|
||||
display: i;
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 12])
|
||||
completions = getCompletions()
|
||||
completions.forEach (completion) ->
|
||||
expect(completion.text).not.toMatch(/;\s*$/)
|
||||
|
||||
it "autocompletes inline property values", ->
|
||||
editor.setText "body { display: }"
|
||||
editor.setCursorBufferPosition([0, 16])
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 24
|
||||
expect(completions[0].text).toBe 'block;'
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
display: block; float:
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 24])
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 4
|
||||
expect(completions[0].text).toBe 'left;'
|
||||
|
||||
it "autocompletes more than one inline property value", ->
|
||||
editor.setText "body { display: block; float: }"
|
||||
editor.setCursorBufferPosition([0, 30])
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 4
|
||||
expect(completions[0].text).toBe 'left;'
|
||||
|
||||
editor.setText "body { display: block; float: left; cursor: alias; text-decoration: }"
|
||||
editor.setCursorBufferPosition([0, 68])
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 5
|
||||
expect(completions[0].text).toBe 'line-through;'
|
||||
|
||||
it "autocompletes inline property values with a prefix", ->
|
||||
editor.setText "body { display: i }"
|
||||
editor.setCursorBufferPosition([0, 17])
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 6
|
||||
expect(completions[0].text).toBe 'inline;'
|
||||
expect(completions[1].text).toBe 'inline-block;'
|
||||
expect(completions[2].text).toBe 'inline-flex;'
|
||||
expect(completions[3].text).toBe 'inline-grid;'
|
||||
expect(completions[4].text).toBe 'inline-table;'
|
||||
expect(completions[5].text).toBe 'inherit;'
|
||||
|
||||
editor.setText "body { display: i}"
|
||||
editor.setCursorBufferPosition([0, 17])
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 6
|
||||
expect(completions[0].text).toBe 'inline;'
|
||||
expect(completions[1].text).toBe 'inline-block;'
|
||||
expect(completions[2].text).toBe 'inline-flex;'
|
||||
expect(completions[3].text).toBe 'inline-grid;'
|
||||
expect(completions[4].text).toBe 'inline-table;'
|
||||
expect(completions[5].text).toBe 'inherit;'
|
||||
|
||||
it "autocompletes inline property values that aren't at the end of the line", ->
|
||||
editor.setText "body { float: display: inline; font-weight: bold; }"
|
||||
editor.setCursorBufferPosition([0, 14]) # right before display
|
||||
completions = getCompletions()
|
||||
expect(completions).toHaveLength 4
|
||||
expect(completions[0].text).toBe 'left;'
|
||||
expect(completions[1].text).toBe 'right;'
|
||||
expect(completions[2].text).toBe 'none;'
|
||||
expect(completions[3].text).toBe 'inherit;'
|
||||
|
||||
it "autocompletes !important in property-value scope", ->
|
||||
editor.setText """
|
||||
body {
|
||||
display: inherit !im
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 22])
|
||||
completions = getCompletions()
|
||||
|
||||
important = null
|
||||
for c in completions
|
||||
important = c if c.displayText is '!important'
|
||||
|
||||
expect(important.displayText).toBe '!important'
|
||||
|
||||
it "does not autocomplete !important in property-name scope", ->
|
||||
editor.setText """
|
||||
body {
|
||||
!im
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 5])
|
||||
completions = getCompletions()
|
||||
|
||||
important = null
|
||||
for c in completions
|
||||
important = c if c.displayText is '!important'
|
||||
|
||||
expect(important).toBe null
|
||||
|
||||
describe "tags", ->
|
||||
it "autocompletes with a prefix", ->
|
||||
editor.setText """
|
||||
ca {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 7
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
expect(completions[0].type).toBe 'tag'
|
||||
expect(completions[0].description).toBe 'Selector for <canvas> elements'
|
||||
expect(completions[1].text).toBe 'code'
|
||||
|
||||
editor.setText """
|
||||
canvas,ca {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 7
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
|
||||
editor.setText """
|
||||
canvas ca {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 7
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
|
||||
editor.setText """
|
||||
canvas, ca {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 10])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 7
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
|
||||
it "does not autocompletes when prefix is preceded by class or id char", ->
|
||||
editor.setText """
|
||||
.ca {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
editor.setText """
|
||||
#ca {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
describe "pseudo selectors", ->
|
||||
it "autocompletes without a prefix", ->
|
||||
editor.setText """
|
||||
div: {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 4])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 43
|
||||
for completion in completions
|
||||
text = (completion.text or completion.snippet)
|
||||
expect(text.length).toBeGreaterThan 0
|
||||
expect(completion.type).toBe 'pseudo-selector'
|
||||
|
||||
# TODO: Enable these tests when we can enable autocomplete and test the
|
||||
# entire path.
|
||||
xit "autocompletes with a prefix", ->
|
||||
editor.setText """
|
||||
div:f {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 5
|
||||
expect(completions[0].text).toBe ':first'
|
||||
expect(completions[0].type).toBe 'pseudo-selector'
|
||||
expect(completions[0].description.length).toBeGreaterThan 0
|
||||
expect(completions[0].descriptionMoreURL.length).toBeGreaterThan 0
|
||||
|
||||
xit "autocompletes with arguments", ->
|
||||
editor.setText """
|
||||
div:nth {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 7])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 4
|
||||
expect(completions[0].snippet).toBe ':nth-child(${1:an+b})'
|
||||
expect(completions[0].type).toBe 'pseudo-selector'
|
||||
expect(completions[0].description.length).toBeGreaterThan 0
|
||||
expect(completions[0].descriptionMoreURL.length).toBeGreaterThan 0
|
||||
|
||||
xit "autocompletes when nothing precedes the colon", ->
|
||||
editor.setText """
|
||||
:f {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 5
|
||||
expect(completions[0].text).toBe ':first'
|
||||
|
||||
Object.keys(packagesToTest).forEach (packageLabel) ->
|
||||
unless packagesToTest[packageLabel].name is 'language-css'
|
||||
describe "#{packageLabel} files", ->
|
||||
beforeEach ->
|
||||
waitsForPromise -> atom.packages.activatePackage(packagesToTest[packageLabel].name)
|
||||
waitsForPromise -> atom.workspace.open(packagesToTest[packageLabel].file)
|
||||
runs -> editor = atom.workspace.getActiveTextEditor()
|
||||
|
||||
it "autocompletes tags and properties when nesting inside the property list", ->
|
||||
editor.setText """
|
||||
.ca {
|
||||
di
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 4])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].text).toBe 'display: '
|
||||
expect(completions[1].text).toBe 'direction: '
|
||||
expect(completions[2].text).toBe 'div'
|
||||
|
||||
# FIXME: This is an issue with the grammar. It thinks nested
|
||||
# pseudo-selectors are meta.property-value.scss/less
|
||||
xit "autocompletes pseudo selectors when nested in LESS and SCSS files", ->
|
||||
editor.setText """
|
||||
.some-class {
|
||||
.a:f
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 6])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 5
|
||||
expect(completions[0].text).toBe ':first'
|
||||
|
||||
it "does not show property names when in a class selector", ->
|
||||
editor.setText """
|
||||
body {
|
||||
.a
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 4])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
it "does not show property names when in an id selector", ->
|
||||
editor.setText """
|
||||
body {
|
||||
#a
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 4])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
it "does not show property names when in a parent selector", ->
|
||||
editor.setText """
|
||||
body {
|
||||
&
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 4])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
it "does not show property names when in a parent selector with a prefix", ->
|
||||
editor.setText """
|
||||
body {
|
||||
&a
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 4])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
describe "SASS files", ->
|
||||
beforeEach ->
|
||||
waitsForPromise -> atom.packages.activatePackage('language-sass')
|
||||
waitsForPromise -> atom.workspace.open('test.sass')
|
||||
runs -> editor = atom.workspace.getActiveTextEditor()
|
||||
|
||||
it "autocompletes property names with a prefix", ->
|
||||
editor.setText """
|
||||
body
|
||||
d
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].text).toBe 'display: '
|
||||
expect(completions[0].displayText).toBe 'display'
|
||||
expect(completions[0].type).toBe 'property'
|
||||
expect(completions[0].replacementPrefix).toBe 'd'
|
||||
expect(completions[0].description.length).toBeGreaterThan 0
|
||||
expect(completions[0].descriptionMoreURL.length).toBeGreaterThan 0
|
||||
expect(completions[1].text).toBe 'direction: '
|
||||
expect(completions[1].displayText).toBe 'direction'
|
||||
expect(completions[1].type).toBe 'property'
|
||||
expect(completions[1].replacementPrefix).toBe 'd'
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
D
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 11
|
||||
expect(completions[0].text).toBe 'display: '
|
||||
expect(completions[1].text).toBe 'direction: '
|
||||
expect(completions[1].replacementPrefix).toBe 'D'
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
d:
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].text).toBe 'display: '
|
||||
expect(completions[1].text).toBe 'direction: '
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
bord
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 6])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].text).toBe 'border: '
|
||||
expect(completions[0].displayText).toBe 'border'
|
||||
expect(completions[0].replacementPrefix).toBe 'bord'
|
||||
|
||||
it "triggers autocomplete when an property name has been inserted", ->
|
||||
spyOn(atom.commands, 'dispatch')
|
||||
suggestion = {type: 'property', text: 'whatever'}
|
||||
provider.onDidInsertSuggestion({editor, suggestion})
|
||||
|
||||
advanceClock 1
|
||||
expect(atom.commands.dispatch).toHaveBeenCalled()
|
||||
|
||||
args = atom.commands.dispatch.mostRecentCall.args
|
||||
expect(args[0].tagName.toLowerCase()).toBe 'atom-text-editor'
|
||||
expect(args[1]).toBe 'autocomplete-plus:activate'
|
||||
|
||||
it "autocompletes property values without a prefix", ->
|
||||
editor.setText """
|
||||
body
|
||||
display:
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 10])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 24
|
||||
for completion in completions
|
||||
expect(completion.text.length).toBeGreaterThan 0
|
||||
expect(completion.description.length).toBeGreaterThan 0
|
||||
expect(completion.descriptionMoreURL.length).toBeGreaterThan 0
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
display:
|
||||
"""
|
||||
editor.setCursorBufferPosition([2, 0])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 24
|
||||
for completion in completions
|
||||
expect(completion.text.length).toBeGreaterThan 0
|
||||
|
||||
it "autocompletes property values with a prefix", ->
|
||||
editor.setText """
|
||||
body
|
||||
display: i
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 12])
|
||||
completions = getCompletions()
|
||||
expect(completions[0].text).toBe 'inline'
|
||||
expect(completions[0].description.length).toBeGreaterThan 0
|
||||
expect(completions[0].descriptionMoreURL.length).toBeGreaterThan 0
|
||||
expect(completions[1].text).toBe 'inline-block'
|
||||
expect(completions[2].text).toBe 'inline-flex'
|
||||
expect(completions[3].text).toBe 'inline-grid'
|
||||
expect(completions[4].text).toBe 'inline-table'
|
||||
expect(completions[5].text).toBe 'inherit'
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
display: I
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 12])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 6
|
||||
expect(completions[0].text).toBe 'inline'
|
||||
expect(completions[1].text).toBe 'inline-block'
|
||||
expect(completions[2].text).toBe 'inline-flex'
|
||||
expect(completions[3].text).toBe 'inline-grid'
|
||||
expect(completions[4].text).toBe 'inline-table'
|
||||
expect(completions[5].text).toBe 'inherit'
|
||||
|
||||
it "autocompletes !important in property-value scope", ->
|
||||
editor.setText """
|
||||
body
|
||||
display: inherit !im
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 22])
|
||||
completions = getCompletions()
|
||||
|
||||
important = null
|
||||
for c in completions
|
||||
important = c if c.displayText is '!important'
|
||||
|
||||
expect(important.displayText).toBe '!important'
|
||||
|
||||
it "does not autocomplete when indented and prefix is not a char", ->
|
||||
editor.setText """
|
||||
body
|
||||
.
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions(activatedManually: false)
|
||||
expect(completions).toBe null
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
#
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions(activatedManually: false)
|
||||
expect(completions).toBe null
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
.foo,
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 7])
|
||||
completions = getCompletions(activatedManually: false)
|
||||
expect(completions).toBe null
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
foo -
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 8])
|
||||
completions = getCompletions(activatedManually: false)
|
||||
expect(completions).toBe null
|
||||
|
||||
# As spaces at end of line will be removed, we'll test with a char
|
||||
# after the space and with the cursor before that char.
|
||||
editor.setCursorBufferPosition([1, 7])
|
||||
completions = getCompletions(activatedManually: false)
|
||||
expect(completions).toBe null
|
||||
|
||||
it 'does not autocomplete when inside a nth-child selector', ->
|
||||
editor.setText """
|
||||
body
|
||||
&:nth-child(4
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 15])
|
||||
completions = getCompletions(activatedManually: false)
|
||||
expect(completions).toBe null
|
||||
|
||||
it 'autocompletes a property name with a dash', ->
|
||||
editor.setText """
|
||||
body
|
||||
border-
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 9])
|
||||
completions = getCompletions(activatedManually: false)
|
||||
expect(completions).not.toBe null
|
||||
|
||||
expect(completions[0].text).toBe 'border: '
|
||||
expect(completions[0].displayText).toBe 'border'
|
||||
expect(completions[0].replacementPrefix).toBe 'border-'
|
||||
|
||||
expect(completions[1].text).toBe 'border-radius: '
|
||||
expect(completions[1].displayText).toBe 'border-radius'
|
||||
expect(completions[1].replacementPrefix).toBe 'border-'
|
||||
|
||||
it "does not autocomplete !important in property-name scope", ->
|
||||
editor.setText """
|
||||
body {
|
||||
!im
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 5])
|
||||
completions = getCompletions()
|
||||
|
||||
important = null
|
||||
for c in completions
|
||||
important = c if c.displayText is '!important'
|
||||
|
||||
expect(important).toBe null
|
||||
|
||||
describe "tags", ->
|
||||
it "autocompletes with a prefix", ->
|
||||
editor.setText """
|
||||
ca
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 7
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
expect(completions[0].type).toBe 'tag'
|
||||
expect(completions[0].description).toBe 'Selector for <canvas> elements'
|
||||
expect(completions[1].text).toBe 'code'
|
||||
|
||||
editor.setText """
|
||||
canvas,ca
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 7
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
|
||||
editor.setText """
|
||||
canvas ca
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 7
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
|
||||
editor.setText """
|
||||
canvas, ca
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 10])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 7
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
|
||||
it "does not autocomplete when prefix is preceded by class or id char", ->
|
||||
editor.setText """
|
||||
.ca
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
editor.setText """
|
||||
#ca
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions).toBe null
|
||||
|
||||
describe "pseudo selectors", ->
|
||||
it "autocompletes without a prefix", ->
|
||||
editor.setText """
|
||||
div:
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 4])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe 43
|
||||
for completion in completions
|
||||
text = (completion.text or completion.snippet)
|
||||
expect(text.length).toBeGreaterThan 0
|
||||
expect(completion.type).toBe 'pseudo-selector'
|
41
packages/autocomplete-css/update.coffee
Normal file
41
packages/autocomplete-css/update.coffee
Normal file
@ -0,0 +1,41 @@
|
||||
# Run this to update the static list of completions stored in the completions.json
|
||||
# file at the root of this repository.
|
||||
|
||||
path = require 'path'
|
||||
fs = require 'fs'
|
||||
request = require 'request'
|
||||
fetchPropertyDescriptions = require './fetch-property-docs'
|
||||
|
||||
PropertiesURL = 'https://raw.githubusercontent.com/adobe/brackets/master/src/extensions/default/CSSCodeHints/CSSProperties.json'
|
||||
|
||||
propertiesPromise = new Promise (resolve) ->
|
||||
request {json: true, url: PropertiesURL}, (error, response, properties) ->
|
||||
if error?
|
||||
console.error(error.message)
|
||||
resolve(null)
|
||||
if response.statusCode isnt 200
|
||||
console.error("Request for CSSProperties.json failed: #{response.statusCode}")
|
||||
resolve(null)
|
||||
resolve(properties)
|
||||
|
||||
propertyDescriptionsPromise = fetchPropertyDescriptions()
|
||||
|
||||
Promise.all([propertiesPromise, propertyDescriptionsPromise]).then (values) ->
|
||||
properties = {}
|
||||
propertiesRaw = values[0]
|
||||
propertyDescriptions = values[1]
|
||||
sortedPropertyNames = JSON.parse(fs.readFileSync(path.join(__dirname, 'sorted-property-names.json')))
|
||||
for propertyName in sortedPropertyNames
|
||||
continue unless metadata = propertiesRaw[propertyName]
|
||||
metadata.description = propertyDescriptions[propertyName]
|
||||
properties[propertyName] = metadata
|
||||
console.warn "No description for property #{propertyName}" unless propertyDescriptions[propertyName]?
|
||||
|
||||
for propertyName of propertiesRaw
|
||||
console.warn "Ignoring #{propertyName}; not in sorted-property-names.json" if sortedPropertyNames.indexOf(propertyName) < 0
|
||||
|
||||
tags = JSON.parse(fs.readFileSync(path.join(__dirname, 'html-tags.json')))
|
||||
pseudoSelectors = JSON.parse(fs.readFileSync(path.join(__dirname, 'pseudo-selectors.json')))
|
||||
|
||||
completions = {tags, properties, pseudoSelectors}
|
||||
fs.writeFileSync(path.join(__dirname, 'completions.json'), "#{JSON.stringify(completions, null, ' ')}\n")
|
1
packages/autocomplete-html/.gitignore
vendored
Normal file
1
packages/autocomplete-html/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
10
packages/autocomplete-html/README.md
Normal file
10
packages/autocomplete-html/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# HTML Autocomplete package
|
||||
|
||||
HTML tag and attribute autocompletions in Pulsar.
|
||||
|
||||
Tag and attribute autocompletions are powered by the list of HTML tags [here](https://github.com/adobe/brackets/blob/master/src/extensions/default/HTMLCodeHints/HtmlTags.json) and HTML attributes [here](https://github.com/adobe/brackets/blob/master/src/extensions/default/HTMLCodeHints/HtmlAttributes.json).
|
||||
Descriptions are powered by [MDN](https://developer.mozilla.org).
|
||||
|
||||
![html-completions](https://cloud.githubusercontent.com/assets/2766036/25668197/ffd24928-2ff3-11e7-85fc-b327ac2287e6.gif)
|
||||
|
||||
You can update the prebuilt list of tags and attributes names and values by running the `update.js` file at the root of the repository and then checking-in the changed `completions.json` file.
|
1919
packages/autocomplete-html/completions.json
Normal file
1919
packages/autocomplete-html/completions.json
Normal file
File diff suppressed because it is too large
Load Diff
113
packages/autocomplete-html/fetch-global-attribute-docs.js
Normal file
113
packages/autocomplete-html/fetch-global-attribute-docs.js
Normal file
@ -0,0 +1,113 @@
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const request = require('request')
|
||||
|
||||
const mdnHTMLURL = 'https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes'
|
||||
const mdnJSONAPI = 'https://developer.mozilla.org/en-US/search.json?topic=html&highlight=false'
|
||||
const AttributesURL = 'https://raw.githubusercontent.com/adobe/brackets/master/src/extensions/default/HTMLCodeHints/HtmlAttributes.json'
|
||||
|
||||
const fetch = () => {
|
||||
const attributesPromise = new Promise((resolve) => {
|
||||
request({json: true, url: AttributesURL}, (error, response, attributes) => {
|
||||
if (error) {
|
||||
console.error(error.message)
|
||||
resolve(null)
|
||||
}
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
console.error(`Request for HtmlAttributes.json failed: ${response.statusCode}`)
|
||||
resolve(null)
|
||||
}
|
||||
|
||||
resolve(attributes)
|
||||
})
|
||||
})
|
||||
|
||||
attributesPromise.then((attributes) => {
|
||||
if (!attributes) return
|
||||
|
||||
const MAX = 10
|
||||
const queue = []
|
||||
for (let attribute in attributes) {
|
||||
// MDN is missing docs for aria attributes and on* event handlers
|
||||
const options = attributes[attribute]
|
||||
if (options.global && !attribute.startsWith('aria') && !attribute.startsWith('on') && (attribute !== 'role')) {
|
||||
queue.push(attribute)
|
||||
}
|
||||
}
|
||||
const running = []
|
||||
const docs = {}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const checkEnd = () => {
|
||||
if ((queue.length === 0) && (running.length === 0)) resolve(docs)
|
||||
}
|
||||
|
||||
const removeRunning = (attributeName) => {
|
||||
const index = running.indexOf(attributeName)
|
||||
if (index > -1) { running.splice(index, 1) }
|
||||
}
|
||||
|
||||
const runNext = () => {
|
||||
checkEnd()
|
||||
if (queue.length !== 0) {
|
||||
const attributeName = queue.pop()
|
||||
running.push(attributeName)
|
||||
run(attributeName)
|
||||
}
|
||||
}
|
||||
|
||||
var run = (attributeName) => {
|
||||
const url = `${mdnJSONAPI}&q=${attributeName}`
|
||||
request({json: true, url}, (error, response, searchResults) => {
|
||||
if (!error && response.statusCode === 200) {
|
||||
handleRequest(attributeName, searchResults)
|
||||
} else {
|
||||
console.error(`Req failed ${url}; ${response.statusCode}, ${error}`)
|
||||
}
|
||||
removeRunning(attributeName)
|
||||
runNext()
|
||||
})
|
||||
}
|
||||
|
||||
var handleRequest = (attributeName, searchResults) => {
|
||||
if (searchResults.documents) {
|
||||
for (let doc of searchResults.documents) {
|
||||
if (doc.url === `${mdnHTMLURL}/${attributeName}`) {
|
||||
docs[attributeName] = filterExcerpt(attributeName, doc.excerpt)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(`Could not find documentation for ${attributeName}`)
|
||||
}
|
||||
|
||||
for (let i = 0; i <= MAX; i++) runNext()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
var filterExcerpt = (attributeName, excerpt) => {
|
||||
const beginningPattern = /^the [a-z-]+ global attribute (is )?(\w+)/i
|
||||
excerpt = excerpt.replace(beginningPattern, (match) => {
|
||||
const matches = beginningPattern.exec(match)
|
||||
const firstWord = matches[2]
|
||||
return firstWord[0].toUpperCase() + firstWord.slice(1)
|
||||
})
|
||||
const periodIndex = excerpt.indexOf('.')
|
||||
if (periodIndex > -1) { excerpt = excerpt.slice(0, periodIndex + 1) }
|
||||
return excerpt
|
||||
}
|
||||
|
||||
// Save a file if run from the command line
|
||||
if (require.main === module) {
|
||||
fetch().then((docs) => {
|
||||
if (docs) {
|
||||
fs.writeFileSync(path.join(__dirname, 'global-attribute-docs.json'), `${JSON.stringify(docs, null, ' ')}\n`)
|
||||
} else {
|
||||
console.error('No docs')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = fetch
|
120
packages/autocomplete-html/fetch-tag-docs.js
Normal file
120
packages/autocomplete-html/fetch-tag-docs.js
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* DS202: Simplify dynamic range loops
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const request = require('request')
|
||||
|
||||
const mdnHTMLURL = 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element'
|
||||
const mdnJSONAPI = 'https://developer.mozilla.org/en-US/search.json?topic=html&highlight=false'
|
||||
const TagsURL = 'https://raw.githubusercontent.com/adobe/brackets/master/src/extensions/default/HTMLCodeHints/HtmlTags.json'
|
||||
|
||||
const fetch = () => {
|
||||
const tagsPromise = new Promise((resolve) => {
|
||||
request({json: true, url: TagsURL}, (error, response, tags) => {
|
||||
if (error != null) {
|
||||
console.error(error.message)
|
||||
resolve(null)
|
||||
}
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
console.error(`Request for HtmlTags.json failed: ${response.statusCode}`)
|
||||
resolve(null)
|
||||
}
|
||||
|
||||
resolve(tags)
|
||||
})
|
||||
})
|
||||
|
||||
return tagsPromise.then((tags) => {
|
||||
if (!tags) return
|
||||
|
||||
const MAX = 10
|
||||
const queue = Object.keys(tags)
|
||||
const running = []
|
||||
const docs = {}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const checkEnd = () => {
|
||||
if ((queue.length === 0) && (running.length === 0)) resolve(docs)
|
||||
}
|
||||
|
||||
const removeRunning = (tagName) => {
|
||||
const index = running.indexOf(tagName)
|
||||
if (index > -1) { return running.splice(index, 1) }
|
||||
}
|
||||
|
||||
const runNext = () => {
|
||||
checkEnd()
|
||||
if (queue.length !== 0) {
|
||||
const tagName = queue.pop()
|
||||
running.push(tagName)
|
||||
run(tagName)
|
||||
}
|
||||
}
|
||||
|
||||
var run = (tagName) => {
|
||||
const url = `${mdnJSONAPI}&q=${tagName}`
|
||||
request({json: true, url}, (error, response, searchResults) => {
|
||||
if ((error == null) && (response.statusCode === 200)) {
|
||||
handleRequest(tagName, searchResults)
|
||||
} else {
|
||||
console.error(`Req failed ${url}; ${response.statusCode}, ${error}`)
|
||||
}
|
||||
removeRunning(tagName)
|
||||
runNext()
|
||||
})
|
||||
}
|
||||
|
||||
var handleRequest = (tagName, searchResults) => {
|
||||
if (searchResults.documents != null) {
|
||||
for (let doc of searchResults.documents) {
|
||||
// MDN groups h1 through h6 under a single "Heading Elements" page
|
||||
if ((doc.url === `${mdnHTMLURL}/${tagName}`) || (/^h\d$/.test(tagName) && (doc.url === `${mdnHTMLURL}/Heading_Elements`))) {
|
||||
if (doc.tags.includes('Obsolete')) {
|
||||
docs[tagName] = `The ${tagName} element is obsolete. Avoid using it and update existing code if possible.`
|
||||
} else if (doc.tags.includes('Deprecated')) {
|
||||
docs[tagName] = `The ${tagName} element is deprecated. Avoid using it and update existing code if possible.`
|
||||
} else {
|
||||
docs[tagName] = filterExcerpt(tagName, doc.excerpt)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(`Could not find documentation for ${tagName}`)
|
||||
}
|
||||
|
||||
for (let i = 0; i <= MAX; i++) { runNext() }
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
var filterExcerpt = (tagName, excerpt) => {
|
||||
const beginningPattern = /^the html [a-z-]+ element (\([^)]+\) )?(is )?(\w+)/i
|
||||
excerpt = excerpt.replace(beginningPattern, (match) => {
|
||||
const matches = beginningPattern.exec(match)
|
||||
const firstWord = matches[3]
|
||||
return firstWord[0].toUpperCase() + firstWord.slice(1)
|
||||
})
|
||||
const periodIndex = excerpt.indexOf('.')
|
||||
if (periodIndex > -1) { excerpt = excerpt.slice(0, periodIndex + 1) }
|
||||
return excerpt
|
||||
}
|
||||
|
||||
// Save a file if run from the command line
|
||||
if (require.main === module) {
|
||||
fetch().then((docs) => {
|
||||
if (docs != null) {
|
||||
fs.writeFileSync(path.join(__dirname, 'tag-docs.json'), `${JSON.stringify(docs, null, ' ')}\n`)
|
||||
} else {
|
||||
console.error('No docs')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = fetch
|
132
packages/autocomplete-html/lib/helpers.js
Normal file
132
packages/autocomplete-html/lib/helpers.js
Normal file
@ -0,0 +1,132 @@
|
||||
const COMPLETIONS = require('../completions.json')
|
||||
|
||||
function getTagNameCompletions (prefix) {
|
||||
const completions = []
|
||||
for (const tag in COMPLETIONS.tags) {
|
||||
const options = COMPLETIONS.tags[tag]
|
||||
if (firstCharsEqual(tag, prefix)) {
|
||||
const {description} = options
|
||||
completions.push({
|
||||
text: tag,
|
||||
type: 'tag',
|
||||
description: description || `HTML <${tag}> tag`,
|
||||
descriptionMoreURL: description ? getTagDocsURL(tag) : null
|
||||
})
|
||||
}
|
||||
}
|
||||
return completions
|
||||
}
|
||||
|
||||
function getAttributeNameCompletions (tag, prefix) {
|
||||
const completions = []
|
||||
const tagAttributes = getTagAttributes(tag)
|
||||
|
||||
for (const attribute of tagAttributes) {
|
||||
if (firstCharsEqual(attribute, prefix)) {
|
||||
const options = COMPLETIONS.attributes[attribute]
|
||||
completions.push({
|
||||
snippet: (options && options.type === 'flag') ? attribute : `${attribute}="$1"$0`,
|
||||
displayText: attribute,
|
||||
type: 'attribute',
|
||||
rightLabel: `<${tag}>`,
|
||||
description: `${attribute} attribute local to <${tag}> tags`,
|
||||
descriptionMoreURL: getLocalAttributeDocsURL(attribute, tag)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for (const attribute in COMPLETIONS.attributes) {
|
||||
const options = COMPLETIONS.attributes[attribute]
|
||||
if (options.global && firstCharsEqual(attribute, prefix)) {
|
||||
completions.push({
|
||||
snippet: options.type === 'flag' ? attribute : `${attribute}="$1"$0`,
|
||||
displayText: attribute,
|
||||
type: 'attribute',
|
||||
description: options.description ? options.description : `Global ${attribute} attribute`,
|
||||
descriptionMoreURL: options.description ? getGlobalAttributeDocsURL(attribute) : null
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return completions
|
||||
}
|
||||
|
||||
function getAttributeValueCompletions (tag, attribute, prefix) {
|
||||
const completions = []
|
||||
|
||||
const values = getAttributeValues(tag, attribute)
|
||||
for (const value of values) {
|
||||
if (firstCharsEqual(value, prefix)) {
|
||||
completions.push(buildAttributeValueCompletion(tag, attribute, value))
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
completions.length === 0 &&
|
||||
COMPLETIONS.attributes[attribute] &&
|
||||
COMPLETIONS.attributes[attribute].type === 'boolean'
|
||||
) {
|
||||
completions.push(buildAttributeValueCompletion(tag, attribute, 'true'))
|
||||
completions.push(buildAttributeValueCompletion(tag, attribute, 'false'))
|
||||
}
|
||||
|
||||
return completions
|
||||
}
|
||||
|
||||
function buildAttributeValueCompletion (tag, attribute, value) {
|
||||
if (COMPLETIONS.attributes[attribute].global) {
|
||||
return {
|
||||
text: value,
|
||||
type: 'value',
|
||||
description: `${value} value for global ${attribute} attribute`,
|
||||
descriptionMoreURL: getGlobalAttributeDocsURL(attribute)
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
text: value,
|
||||
type: 'value',
|
||||
rightLabel: `<${tag}>`,
|
||||
description: `${value} value for ${attribute} attribute local to <${tag}>`,
|
||||
descriptionMoreURL: getLocalAttributeDocsURL(attribute, tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getAttributeValues (tag, attribute) {
|
||||
// Some local attributes are valid for multiple tags but have different attribute values
|
||||
// To differentiate them, they are identified in the completions file as tag/attribute
|
||||
let result = COMPLETIONS.attributes[`${tag}/${attribute}`]
|
||||
if (result && result.attribOption) return result.attribOption
|
||||
result = COMPLETIONS.attributes[attribute]
|
||||
if (result && result.attribOption) return result.attribOption
|
||||
return []
|
||||
}
|
||||
|
||||
function getTagAttributes (tag) {
|
||||
let result = COMPLETIONS.tags[tag]
|
||||
if (result && result.attributes) return result.attributes
|
||||
return []
|
||||
}
|
||||
|
||||
function getLocalAttributeDocsURL (attribute, tag) {
|
||||
return `${getTagDocsURL(tag)}#attr-${attribute}`
|
||||
}
|
||||
|
||||
function getGlobalAttributeDocsURL (attribute) {
|
||||
return `https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/${attribute}`
|
||||
}
|
||||
|
||||
function getTagDocsURL (tag) {
|
||||
return `https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${tag}`
|
||||
}
|
||||
|
||||
function firstCharsEqual (a, b) {
|
||||
if (b.length === 0) return true
|
||||
return a[0].toLowerCase() === b[0].toLowerCase()
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getTagNameCompletions,
|
||||
getAttributeNameCompletions,
|
||||
getAttributeValueCompletions
|
||||
}
|
36
packages/autocomplete-html/lib/main.js
Normal file
36
packages/autocomplete-html/lib/main.js
Normal file
@ -0,0 +1,36 @@
|
||||
const getSuggestionsWithTreeSitter = require('./tree-sitter-provider')
|
||||
const getSuggestionsWithTextMate = require('./text-mate-provider')
|
||||
|
||||
const provider = {
|
||||
selector: '.text.html',
|
||||
disableForSelector: '.text.html .comment',
|
||||
priority: 1,
|
||||
filterSuggestions: true,
|
||||
|
||||
getSuggestions (request) {
|
||||
if (request.editor.getBuffer().getLanguageMode().tree) {
|
||||
return getSuggestionsWithTreeSitter(request)
|
||||
} else {
|
||||
return getSuggestionsWithTextMate(request)
|
||||
}
|
||||
},
|
||||
|
||||
onDidInsertSuggestion ({editor, suggestion}) {
|
||||
if (suggestion.type === 'attribute') {
|
||||
setTimeout(this.triggerAutocomplete.bind(this, editor), 1)
|
||||
}
|
||||
},
|
||||
|
||||
triggerAutocomplete (editor) {
|
||||
atom.commands.dispatch(
|
||||
editor.getElement(),
|
||||
'autocomplete-plus:activate',
|
||||
{activatedManually: false}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
activate () {},
|
||||
getProvider () { return provider }
|
||||
}
|
127
packages/autocomplete-html/lib/text-mate-provider.js
Normal file
127
packages/autocomplete-html/lib/text-mate-provider.js
Normal file
@ -0,0 +1,127 @@
|
||||
const {
|
||||
getTagNameCompletions,
|
||||
getAttributeNameCompletions,
|
||||
getAttributeValueCompletions
|
||||
} = require('./helpers')
|
||||
|
||||
const attributePattern = /\s+([a-zA-Z][-a-zA-Z]*)\s*=\s*$/
|
||||
const tagPattern = /<([a-zA-Z][-a-zA-Z]*)(?:\s|$)/
|
||||
|
||||
module.exports = function (request) {
|
||||
let {editor, bufferPosition, prefix} = request
|
||||
prefix = prefix.trim()
|
||||
|
||||
if (isAttributeValueStart(request)) {
|
||||
const tag = getPreviousTag(editor, bufferPosition)
|
||||
const attribute = getPreviousAttribute(editor, bufferPosition)
|
||||
return getAttributeValueCompletions(tag, attribute, prefix)
|
||||
}
|
||||
|
||||
if (isAttributeStart(request)) {
|
||||
const tag = getPreviousTag(editor, bufferPosition)
|
||||
return getAttributeNameCompletions(tag, prefix)
|
||||
}
|
||||
|
||||
if (isTagStart(request)) {
|
||||
const ignorePrefix = editor.getTextInRange([
|
||||
[bufferPosition.row, bufferPosition.column - 1],
|
||||
bufferPosition
|
||||
]) === '<'
|
||||
return getTagNameCompletions(ignorePrefix ? '' : prefix)
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
function isTagStart ({prefix, scopeDescriptor, bufferPosition, editor}) {
|
||||
if (prefix.trim() && (prefix.indexOf('<') === -1)) {
|
||||
return hasTagScope(scopeDescriptor.getScopesArray())
|
||||
}
|
||||
|
||||
// autocomplete-plus's default prefix setting does not capture <. Manually check for it.
|
||||
prefix = editor.getTextInRange([[bufferPosition.row, bufferPosition.column - 1], bufferPosition])
|
||||
|
||||
const scopes = scopeDescriptor.getScopesArray()
|
||||
|
||||
// Don't autocomplete in embedded languages
|
||||
return (prefix === '<') && (scopes[0] === 'text.html.basic') && (scopes.length === 1)
|
||||
}
|
||||
|
||||
function isAttributeStart ({prefix, scopeDescriptor, bufferPosition, editor}) {
|
||||
const scopes = scopeDescriptor.getScopesArray()
|
||||
if (!getPreviousAttribute(editor, bufferPosition) && prefix && !prefix.trim()) {
|
||||
return hasTagScope(scopes)
|
||||
}
|
||||
|
||||
const previousBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - 1)]
|
||||
const previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
|
||||
const previousScopesArray = previousScopes.getScopesArray()
|
||||
|
||||
if (previousScopesArray.includes('entity.other.attribute-name.html')) return true
|
||||
if (!hasTagScope(scopes)) return false
|
||||
|
||||
// autocomplete here: <tag |>
|
||||
// not here: <tag >|
|
||||
return (
|
||||
scopes.includes('punctuation.definition.tag.end.html') &&
|
||||
!previousScopesArray.includes('punctuation.definition.tag.end.html')
|
||||
)
|
||||
}
|
||||
|
||||
function isAttributeValueStart ({scopeDescriptor, bufferPosition, editor}) {
|
||||
const scopes = scopeDescriptor.getScopesArray()
|
||||
|
||||
const previousBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - 1)]
|
||||
const previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
|
||||
const previousScopesArray = previousScopes.getScopesArray()
|
||||
|
||||
// autocomplete here: attribute="|"
|
||||
// not here: attribute=|""
|
||||
// or here: attribute=""|
|
||||
// or here: attribute="""|
|
||||
return (
|
||||
hasStringScope(scopes) &&
|
||||
hasStringScope(previousScopesArray) &&
|
||||
!previousScopesArray.includes('punctuation.definition.string.end.html') &&
|
||||
hasTagScope(scopes) &&
|
||||
getPreviousAttribute(editor, bufferPosition) != null
|
||||
)
|
||||
}
|
||||
|
||||
function hasTagScope (scopes) {
|
||||
for (let scope of scopes) {
|
||||
if (scope.startsWith('meta.tag.') && scope.endsWith('.html')) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function hasStringScope (scopes) {
|
||||
return (
|
||||
scopes.includes('string.quoted.double.html') ||
|
||||
scopes.includes('string.quoted.single.html')
|
||||
)
|
||||
}
|
||||
|
||||
function getPreviousTag (editor, bufferPosition) {
|
||||
let {row} = bufferPosition
|
||||
while (row >= 0) {
|
||||
const match = tagPattern.exec(editor.lineTextForBufferRow(row))
|
||||
const tag = match && match[1]
|
||||
if (tag) return tag
|
||||
row--
|
||||
}
|
||||
}
|
||||
|
||||
function getPreviousAttribute (editor, bufferPosition) {
|
||||
// Remove everything until the opening quote (if we're in a string)
|
||||
let quoteIndex = bufferPosition.column - 1 // Don't start at the end of the line
|
||||
while (quoteIndex) {
|
||||
const scopes = editor.scopeDescriptorForBufferPosition([bufferPosition.row, quoteIndex])
|
||||
const scopesArray = scopes.getScopesArray()
|
||||
if (!hasStringScope(scopesArray) || (scopesArray.indexOf('punctuation.definition.string.begin.html') !== -1)) break
|
||||
quoteIndex--
|
||||
}
|
||||
|
||||
const match = attributePattern.exec(editor.getTextInRange([[bufferPosition.row, 0], [bufferPosition.row, quoteIndex]]))
|
||||
return match && match[1]
|
||||
}
|
126
packages/autocomplete-html/lib/tree-sitter-provider.js
Normal file
126
packages/autocomplete-html/lib/tree-sitter-provider.js
Normal file
@ -0,0 +1,126 @@
|
||||
const {
|
||||
getTagNameCompletions,
|
||||
getAttributeNameCompletions,
|
||||
getAttributeValueCompletions
|
||||
} = require('./helpers')
|
||||
|
||||
module.exports = function ({editor, bufferPosition}) {
|
||||
let node = tokenBeforePosition(editor, bufferPosition)
|
||||
if (!node) return []
|
||||
|
||||
switch (node.type) {
|
||||
case '<': {
|
||||
if (!bufferPosition.isEqual(node.endPosition)) break
|
||||
return getTagNameCompletions('')
|
||||
}
|
||||
|
||||
case 'tag_name': {
|
||||
if (bufferPosition.isEqual(node.endPosition)) {
|
||||
const {previousSibling} = node
|
||||
if (previousSibling && previousSibling.endIndex === node.startIndex) {
|
||||
return getTagNameCompletions(node.text)
|
||||
}
|
||||
} else {
|
||||
return getAttributeNameCompletions(node.text, '')
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'attribute_name': {
|
||||
if (!bufferPosition.isEqual(node.endPosition)) break
|
||||
const tagNode = node.parent.parent
|
||||
const tagNameNode = tagNode.child(1)
|
||||
if (tagNameNode) {
|
||||
return getAttributeNameCompletions(tagNameNode.text, node.text)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'attribute_value':
|
||||
case '"':
|
||||
case '\'': {
|
||||
let prefix = ''
|
||||
if (node.type === 'attribute_value') {
|
||||
prefix = node.text
|
||||
node = node.previousSibling
|
||||
}
|
||||
|
||||
const predecessor = tokenBefore(node)
|
||||
if (!predecessor || predecessor.type !== '=') return []
|
||||
const containerNode = node.closest(['start_tag', 'self_closing_tag', 'ERROR'])
|
||||
const tagNameNode = containerNode.descendantsOfType(
|
||||
'tag_name'
|
||||
)[0]
|
||||
|
||||
// Get the last attribute name before the quote
|
||||
const attributeNameNode = containerNode.descendantsOfType(
|
||||
'attribute_name',
|
||||
null,
|
||||
node.startPosition
|
||||
).pop()
|
||||
if (tagNameNode && attributeNameNode) {
|
||||
return getAttributeValueCompletions(tagNameNode.text, attributeNameNode.text, prefix)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
function tokenBeforePosition (editor, position) {
|
||||
const languageMode = editor.getBuffer().getLanguageMode()
|
||||
let node = languageMode.getSyntaxNodeAtPosition(
|
||||
position,
|
||||
(node, grammar) => grammar.scopeName === 'text.html.basic'
|
||||
)
|
||||
if (!node) return null
|
||||
node = lastDescendant(node)
|
||||
|
||||
while (
|
||||
position.isLessThan(node.endPosition) ||
|
||||
node.isMissing() ||
|
||||
node.type === 'text'
|
||||
) {
|
||||
node = tokenBefore(node)
|
||||
if (!node) return null
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
const nodesToSearch = new Set([
|
||||
'<',
|
||||
'tag_name',
|
||||
'attribute_name',
|
||||
'attribute_value',
|
||||
'"',
|
||||
'\''
|
||||
])
|
||||
|
||||
function tokenBefore (node) {
|
||||
for (;;) {
|
||||
const {previousSibling} = node
|
||||
if (previousSibling) {
|
||||
return lastDescendant(previousSibling)
|
||||
}
|
||||
|
||||
const {parent} = node
|
||||
if (parent) {
|
||||
node = parent
|
||||
if(nodesToSearch.has(node.type)) return node
|
||||
continue
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function lastDescendant (node) {
|
||||
let {lastChild} = node
|
||||
while (lastChild) {
|
||||
node = lastChild
|
||||
lastChild = node.lastChild
|
||||
}
|
||||
return node
|
||||
}
|
873
packages/autocomplete-html/package-lock.json
generated
Normal file
873
packages/autocomplete-html/package-lock.json
generated
Normal file
@ -0,0 +1,873 @@
|
||||
{
|
||||
"name": "autocomplete-html",
|
||||
"version": "0.8.9",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "autocomplete-html",
|
||||
"version": "0.8.9",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"request": "^2.53.0"
|
||||
},
|
||||
"engines": {
|
||||
"atom": ">=0.174.0 <2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/aws4": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"node_modules/caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
|
||||
"dev": true,
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
]
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/har-validator": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"deprecated": "this library is no longer supported",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8",
|
||||
"npm": ">=1.3.7"
|
||||
}
|
||||
},
|
||||
"node_modules/is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-schema": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
|
||||
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jsprim": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
|
||||
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.4.0",
|
||||
"verror": "1.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/psl": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
|
||||
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/request": {
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sshpk": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
|
||||
"integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
},
|
||||
"bin": {
|
||||
"sshpk-conv": "bin/sshpk-conv",
|
||||
"sshpk-sign": "bin/sshpk-sign",
|
||||
"sshpk-verify": "bin/sshpk-verify"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"uuid": "bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
|
||||
"dev": true,
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
],
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||
"dev": true
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
|
||||
"dev": true
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
|
||||
"dev": true
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
|
||||
"dev": true
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
|
||||
"dev": true
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"dev": true
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
|
||||
"dev": true
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
|
||||
"dev": true
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
|
||||
"dev": true
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
|
||||
"dev": true
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
|
||||
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
|
||||
"dev": true
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
|
||||
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.4.0",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
||||
"dev": true
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
|
||||
"dev": true
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"dev": true
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
|
||||
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
|
||||
"dev": true
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
|
||||
"integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
|
||||
"dev": true
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"dev": true
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
packages/autocomplete-html/package.json
Normal file
21
packages/autocomplete-html/package.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "autocomplete-html",
|
||||
"version": "0.8.9",
|
||||
"description": "HTML element and attribute autocompletions",
|
||||
"main": "./lib/main",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/pulsar-edit/pulsar",
|
||||
"engines": {
|
||||
"atom": ">=0.174.0 <2.0.0"
|
||||
},
|
||||
"providedServices": {
|
||||
"autocomplete.provider": {
|
||||
"versions": {
|
||||
"2.0.0": "getProvider"
|
||||
}
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"request": "^2.53.0"
|
||||
}
|
||||
}
|
521
packages/autocomplete-html/spec/provider-spec.js
Normal file
521
packages/autocomplete-html/spec/provider-spec.js
Normal file
@ -0,0 +1,521 @@
|
||||
describe('HTML autocompletions', () => {
|
||||
let editor, provider
|
||||
|
||||
function getCompletions () {
|
||||
const cursor = editor.getLastCursor()
|
||||
const bufferPosition = cursor.getBufferPosition()
|
||||
const scopeDescriptor = cursor.getScopeDescriptor()
|
||||
const line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
|
||||
// https://github.com/atom/autocomplete-plus/blob/9506a5c5fafca29003c59566cfc2b3ac37080973/lib/autocomplete-manager.js#L57
|
||||
const prefixMatch = /(\b|['"~`!@#$%^&*(){}[\]=+,/?>])((\w+[\w-]*)|([.:;[{(< ]+))$/.exec(line)
|
||||
const prefix = prefixMatch ? prefixMatch[2] : ''
|
||||
return provider.getSuggestions({editor, bufferPosition, scopeDescriptor, prefix})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
waitsForPromise(() => atom.packages.activatePackage('autocomplete-html'))
|
||||
waitsForPromise(() => atom.packages.activatePackage('language-html'))
|
||||
waitsForPromise(() => atom.workspace.open('test.html'))
|
||||
|
||||
runs(() => provider = atom.packages.getActivePackage('autocomplete-html').mainModule.getProvider())
|
||||
runs(() => editor = atom.workspace.getActiveTextEditor())
|
||||
})
|
||||
|
||||
it('returns no completions when not at the start of a tag', () => {
|
||||
editor.setText('')
|
||||
expect(getCompletions().length).toBe(0)
|
||||
|
||||
editor.setText('d')
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
expect(getCompletions().length).toBe(0)
|
||||
editor.setCursorBufferPosition([0, 1])
|
||||
expect(getCompletions().length).toBe(0)
|
||||
})
|
||||
|
||||
it('returns no completions in style tags', () => {
|
||||
editor.setText(`\
|
||||
<style>
|
||||
<
|
||||
</style>\
|
||||
`
|
||||
)
|
||||
editor.setCursorBufferPosition([1, 1])
|
||||
expect(getCompletions().length).toBe(0)
|
||||
})
|
||||
|
||||
it('returns no completions in script tags', () => {
|
||||
editor.setText(`\
|
||||
<script>
|
||||
<
|
||||
</script>\
|
||||
`
|
||||
)
|
||||
editor.setCursorBufferPosition([1, 1])
|
||||
expect(getCompletions().length).toBe(0)
|
||||
})
|
||||
|
||||
it('autcompletes tag names without a prefix', () => {
|
||||
editor.setText('<')
|
||||
editor.setCursorBufferPosition([0, 1])
|
||||
|
||||
const completions = getCompletions()
|
||||
expect(completions.length).toBe(113)
|
||||
expect(completions[0].description).toContain('Creates a hyperlink to other web pages')
|
||||
expect(completions[0].descriptionMoreURL.endsWith('/HTML/Element/a')).toBe(true)
|
||||
|
||||
for (let completion of completions) {
|
||||
expect(completion.text.length).toBeGreaterThan(0)
|
||||
expect(completion.description.length).toBeGreaterThan(0)
|
||||
expect(completion.type).toBe('tag')
|
||||
}
|
||||
})
|
||||
|
||||
it('autocompletes tag names with a prefix', () => {
|
||||
editor.setText('<d')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(9)
|
||||
|
||||
expect(completions[0].text).toBe('datalist')
|
||||
expect(completions[0].type).toBe('tag')
|
||||
expect(completions[0].descriptionMoreURL.endsWith('/HTML/Element/datalist')).toBe(true)
|
||||
expect(completions[1].text).toBe('dd')
|
||||
expect(completions[2].text).toBe('del')
|
||||
expect(completions[3].text).toBe('details')
|
||||
expect(completions[4].text).toBe('dfn')
|
||||
expect(completions[5].text).toBe('dialog')
|
||||
expect(completions[6].text).toBe('div')
|
||||
expect(completions[7].text).toBe('dl')
|
||||
expect(completions[8].text).toBe('dt')
|
||||
|
||||
editor.setText('<D')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(9)
|
||||
|
||||
expect(completions[0].text).toBe('datalist')
|
||||
expect(completions[0].type).toBe('tag')
|
||||
expect(completions[1].text).toBe('dd')
|
||||
expect(completions[2].text).toBe('del')
|
||||
expect(completions[3].text).toBe('details')
|
||||
expect(completions[4].text).toBe('dfn')
|
||||
expect(completions[5].text).toBe('dialog')
|
||||
expect(completions[6].text).toBe('div')
|
||||
expect(completions[7].text).toBe('dl')
|
||||
expect(completions[8].text).toBe('dt')
|
||||
})
|
||||
|
||||
it("does not autocomplete tag names if there's a space after the <", () => {
|
||||
editor.setText('< ')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
|
||||
editor.setText('< h')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not provide a descriptionMoreURL if the tag does not have a unique description', () => {
|
||||
// ilayer does not have an associated MDN page as of April 27, 2017
|
||||
editor.setText('<i')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
|
||||
const completions = getCompletions()
|
||||
|
||||
expect(completions[2].text).toBe('ilayer')
|
||||
expect(completions[2].description).toBe('HTML <ilayer> tag')
|
||||
expect(completions[2].descriptionMoreURL).toBeNull()
|
||||
})
|
||||
|
||||
it('autocompletes attribute names without a prefix', () => {
|
||||
editor.setText('<div ')
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(86)
|
||||
expect(completions[0].description).toContain('Provides a hint for generating a keyboard shortcut')
|
||||
expect(completions[0].descriptionMoreURL.endsWith('/HTML/Global_attributes/accesskey')).toBe(true)
|
||||
|
||||
for (var completion of completions) {
|
||||
expect(completion.snippet.length).toBeGreaterThan(0)
|
||||
expect(completion.displayText.length).toBeGreaterThan(0)
|
||||
expect(completion.description.length).toBeGreaterThan(0)
|
||||
expect(completion.type).toBe('attribute')
|
||||
}
|
||||
|
||||
editor.setText('<marquee ')
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(98)
|
||||
expect(completions[0].rightLabel).toBe('<marquee>')
|
||||
expect(completions[0].descriptionMoreURL.endsWith('/HTML/Element/marquee#attr-align')).toBe(true)
|
||||
|
||||
for (completion of completions) {
|
||||
expect(completion.snippet.length).toBeGreaterThan(0)
|
||||
expect(completion.displayText.length).toBeGreaterThan(0)
|
||||
expect(completion.description.length).toBeGreaterThan(0)
|
||||
expect(completion.type).toBe('attribute')
|
||||
}
|
||||
|
||||
editor.setText('<div >')
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(0)
|
||||
for (completion of completions) { expect(completion.type).toBe('attribute') }
|
||||
|
||||
editor.setText('<div >')
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(0)
|
||||
for (completion of completions) {
|
||||
expect(completion.type).toBe('attribute')
|
||||
}
|
||||
})
|
||||
|
||||
it('autocompletes attribute names with a prefix', () => {
|
||||
editor.setText('<div c')
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].snippet).toBe('class="$1"$0')
|
||||
expect(completions[0].displayText).toBe('class')
|
||||
expect(completions[0].type).toBe('attribute')
|
||||
expect(completions[1].displayText).toBe('contenteditable')
|
||||
expect(completions[2].displayText).toBe('contextmenu')
|
||||
|
||||
editor.setText('<div C')
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].displayText).toBe('class')
|
||||
expect(completions[1].displayText).toBe('contenteditable')
|
||||
expect(completions[2].displayText).toBe('contextmenu')
|
||||
|
||||
editor.setText('<div c>')
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].displayText).toBe('class')
|
||||
expect(completions[1].displayText).toBe('contenteditable')
|
||||
expect(completions[2].displayText).toBe('contextmenu')
|
||||
|
||||
editor.setText('<div c></div>')
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].displayText).toBe('class')
|
||||
expect(completions[1].displayText).toBe('contenteditable')
|
||||
expect(completions[2].displayText).toBe('contextmenu')
|
||||
|
||||
editor.setText('<marquee di')
|
||||
editor.setCursorBufferPosition([0, 12])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions[0].displayText).toBe('direction')
|
||||
expect(completions[1].displayText).toBe('dir')
|
||||
|
||||
editor.setText('<marquee dI')
|
||||
editor.setCursorBufferPosition([0, 12])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions[0].displayText).toBe('direction')
|
||||
expect(completions[1].displayText).toBe('dir')
|
||||
})
|
||||
|
||||
it('autocompletes attribute names without a prefix surrounded by whitespace', () => {
|
||||
editor.setText('<select autofocus')
|
||||
editor.setCursorBufferPosition([0, 8])
|
||||
|
||||
const completions = getCompletions()
|
||||
for (let completion of completions) { expect(completion.type).toBe('attribute') }
|
||||
expect(completions[0].displayText).toBe('autofocus')
|
||||
})
|
||||
|
||||
it('autocompletes attribute names with a prefix surrounded by whitespace', () => {
|
||||
editor.setText('<select o autofocus')
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
|
||||
const completions = getCompletions()
|
||||
for (let completion of completions) { expect(completion.type).toBe('attribute') }
|
||||
expect(completions[0].displayText).toBe('onabort')
|
||||
})
|
||||
|
||||
it("respects the 'flag' type when autocompleting attribute names", () => {
|
||||
editor.setText('<select ')
|
||||
editor.setCursorBufferPosition([0, 8])
|
||||
|
||||
const completions = getCompletions()
|
||||
expect(completions[0].snippet).toBe('autofocus')
|
||||
})
|
||||
|
||||
it('does not autocomplete attribute names in between an attribute name and value', () => {
|
||||
editor.setText('<select autofocus=""')
|
||||
editor.setCursorBufferPosition([0, 18])
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
|
||||
editor.setText('<select autofocus= ""')
|
||||
editor.setCursorBufferPosition([0, 18])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
|
||||
editor.setText('<select autofocus= ""')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
|
||||
editor.setText('<select autofocus= ""')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not autocomplete attribute names outside of a tag', () => {
|
||||
editor.setText('<kbd>')
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
|
||||
expect(getCompletions().length).toBe(0)
|
||||
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
|
||||
expect(getCompletions().length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not throw when a local attribute is not in the attributes list', () => {
|
||||
// Some tags, like body, have local attributes that are not present in the top-level attributes array
|
||||
editor.setText('<body ')
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
|
||||
const completions = getCompletions()
|
||||
expect(completions[0].displayText).toBe('onafterprint')
|
||||
})
|
||||
|
||||
it('does not provide a descriptionMoreURL if the attribute does not have a unique description', () => {
|
||||
editor.setText('<input on')
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
|
||||
const completions = getCompletions()
|
||||
|
||||
expect(completions[0].displayText).toBe('onabort')
|
||||
expect(completions[0].description).toBe('Global onabort attribute')
|
||||
expect(completions[0].descriptionMoreURL).toBeNull()
|
||||
})
|
||||
|
||||
it('autocompletes attribute values without a prefix', () => {
|
||||
editor.setText('<marquee behavior=""')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].text).toBe('scroll')
|
||||
expect(completions[0].type).toBe('value')
|
||||
expect(completions[0].description.length).toBeGreaterThan(0)
|
||||
expect(completions[0].descriptionMoreURL.endsWith('/HTML/Element/marquee#attr-behavior')).toBe(true)
|
||||
expect(completions[1].text).toBe('slide')
|
||||
expect(completions[2].text).toBe('alternate')
|
||||
|
||||
editor.setText('<marquee behavior="')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].text).toBe('scroll')
|
||||
expect(completions[1].text).toBe('slide')
|
||||
expect(completions[2].text).toBe('alternate')
|
||||
|
||||
editor.setText('<marquee behavior=\'')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].text).toBe('scroll')
|
||||
expect(completions[1].text).toBe('slide')
|
||||
expect(completions[2].text).toBe('alternate')
|
||||
|
||||
editor.setText('<marquee behavior=\'\'')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].text).toBe('scroll')
|
||||
expect(completions[1].text).toBe('slide')
|
||||
expect(completions[2].text).toBe('alternate')
|
||||
})
|
||||
|
||||
it('autocompletes attribute values with a prefix', () => {
|
||||
editor.setText('<html behavior="" lang="e"')
|
||||
editor.setCursorBufferPosition([0, 25])
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(6)
|
||||
|
||||
expect(completions[0].text).toBe('eu')
|
||||
expect(completions[0].type).toBe('value')
|
||||
expect(completions[1].text).toBe('en')
|
||||
expect(completions[2].text).toBe('eo')
|
||||
expect(completions[3].text).toBe('et')
|
||||
expect(completions[4].text).toBe('el')
|
||||
expect(completions[5].text).toBe('es')
|
||||
|
||||
editor.setText('<html behavior="" lang="E"')
|
||||
editor.setCursorBufferPosition([0, 25])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(6)
|
||||
|
||||
expect(completions[0].text).toBe('eu')
|
||||
expect(completions[1].text).toBe('en')
|
||||
expect(completions[2].text).toBe('eo')
|
||||
expect(completions[3].text).toBe('et')
|
||||
expect(completions[4].text).toBe('el')
|
||||
expect(completions[5].text).toBe('es')
|
||||
|
||||
editor.setText('<html behavior="" lang=\'e\'')
|
||||
editor.setCursorBufferPosition([0, 25])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(6)
|
||||
|
||||
expect(completions[0].text).toBe('eu')
|
||||
expect(completions[1].text).toBe('en')
|
||||
expect(completions[2].text).toBe('eo')
|
||||
expect(completions[3].text).toBe('et')
|
||||
expect(completions[4].text).toBe('el')
|
||||
expect(completions[5].text).toBe('es')
|
||||
})
|
||||
|
||||
it('autocompletes ambiguous attribute values', () => {
|
||||
editor.setText('<button type=""')
|
||||
editor.setCursorBufferPosition([0, 14])
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].text).toBe('button')
|
||||
expect(completions[0].type).toBe('value')
|
||||
expect(completions[0].description.length).toBeGreaterThan(0)
|
||||
expect(completions[0].descriptionMoreURL.endsWith('/HTML/Element/button#attr-type')).toBe(true)
|
||||
expect(completions[1].text).toBe('reset')
|
||||
expect(completions[2].text).toBe('submit')
|
||||
|
||||
editor.setText('<link rel=""')
|
||||
editor.setCursorBufferPosition([0, 11])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(13)
|
||||
expect(completions.map(_ => _.text)).toContain('stylesheet')
|
||||
|
||||
expect(completions[0].text).toBe('alternate')
|
||||
expect(completions[0].type).toBe('value')
|
||||
expect(completions[0].description.length).toBeGreaterThan(0)
|
||||
expect(completions[0].descriptionMoreURL.endsWith('/HTML/Element/link#attr-rel')).toBe(true)
|
||||
})
|
||||
|
||||
it("provides 'true' and 'false' suggestions when autocompleting boolean attributes", () => {
|
||||
editor.setText('<html contenteditable=""')
|
||||
editor.setCursorBufferPosition([0, 23])
|
||||
|
||||
const completions = getCompletions()
|
||||
expect(completions.length).toBe(2)
|
||||
expect(completions[0].text).toBe('true')
|
||||
expect(completions[1].text).toBe('false')
|
||||
})
|
||||
|
||||
it('does not attempt to autocomplete values before the beginning of a string', () => {
|
||||
editor.setText('<button type=""')
|
||||
editor.setCursorBufferPosition([0, 13])
|
||||
|
||||
let completions = []
|
||||
expect(() => completions = getCompletions()).not.toThrow()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not attempt to autocomplete values after the end of a string', () => {
|
||||
editor.setText('<button type=""')
|
||||
editor.setCursorBufferPosition([0, 15])
|
||||
|
||||
let completions = []
|
||||
expect(() => completions = getCompletions()).not.toThrow()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not throw when quotes are in the attribute value', () => {
|
||||
editor.setText('<button type="\'"')
|
||||
editor.setCursorBufferPosition([0, 15])
|
||||
|
||||
expect(() => getCompletions()).not.toThrow()
|
||||
})
|
||||
|
||||
it("does not autocomplete attribute values if there isn't a corresponding attribute", () => {
|
||||
editor.setText('<button type="""')
|
||||
editor.setCursorBufferPosition([0, 16])
|
||||
|
||||
let completions = []
|
||||
expect(() => completions = getCompletions()).not.toThrow()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not throw when attempting to autocomplete values for nonexistent attributes', () => {
|
||||
editor.setText('<button typ=""')
|
||||
editor.setCursorBufferPosition([0, 13])
|
||||
|
||||
let completions = []
|
||||
expect(() => completions = getCompletions()).not.toThrow()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('triggers autocomplete when an attibute has been inserted', () => {
|
||||
spyOn(atom.commands, 'dispatch')
|
||||
const suggestion = {type: 'attribute', text: 'whatever'}
|
||||
provider.onDidInsertSuggestion({editor, suggestion})
|
||||
|
||||
advanceClock(1)
|
||||
expect(atom.commands.dispatch).toHaveBeenCalled()
|
||||
|
||||
const { args } = atom.commands.dispatch.mostRecentCall
|
||||
expect(args[0].tagName.toLowerCase()).toBe('atom-text-editor')
|
||||
expect(args[1]).toBe('autocomplete-plus:activate')
|
||||
})
|
||||
|
||||
it('does not error in EJS documents', () => {
|
||||
waitsForPromise(async () => {
|
||||
await atom.workspace.open('test.html.ejs')
|
||||
editor = atom.workspace.getActiveTextEditor()
|
||||
editor.setText('<span><% a = ""; %></span>')
|
||||
})
|
||||
|
||||
waitsForPromise(() => {
|
||||
return atom.packages.activatePackage('language-javascript')
|
||||
})
|
||||
|
||||
runs(() => {
|
||||
editor.setCursorBufferPosition([0, editor.getText().indexOf('""') + 1])
|
||||
expect(() => getCompletions()).not.toThrow()
|
||||
})
|
||||
})
|
||||
})
|
73
packages/autocomplete-html/update.js
Normal file
73
packages/autocomplete-html/update.js
Normal file
@ -0,0 +1,73 @@
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const request = require('request')
|
||||
const fetchTagDescriptions = require('./fetch-tag-docs')
|
||||
const fetchGlobalAttributeDescriptions = require('./fetch-global-attribute-docs')
|
||||
|
||||
const TagsURL = 'https://raw.githubusercontent.com/adobe/brackets/master/src/extensions/default/HTMLCodeHints/HtmlTags.json'
|
||||
const AttributesURL = 'https://raw.githubusercontent.com/adobe/brackets/master/src/extensions/default/HTMLCodeHints/HtmlAttributes.json'
|
||||
|
||||
const tagsPromise = new Promise((resolve) => {
|
||||
request({json: true, url: TagsURL}, (error, response, tags) => {
|
||||
if (error != null) {
|
||||
console.error(error.message)
|
||||
resolve(null)
|
||||
}
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
console.error(`Request for HtmlTags.json failed: ${response.statusCode}`)
|
||||
resolve(null)
|
||||
}
|
||||
|
||||
for (let tag in tags) {
|
||||
const options = tags[tag]
|
||||
if ((options.attributes != null ? options.attributes.length : undefined) === 0) { delete options.attributes }
|
||||
}
|
||||
|
||||
resolve(tags)
|
||||
})
|
||||
})
|
||||
|
||||
const tagDescriptionsPromise = fetchTagDescriptions()
|
||||
|
||||
const attributesPromise = new Promise((resolve) => {
|
||||
return request({json: true, url: AttributesURL}, (error, response, attributes) => {
|
||||
if (error != null) {
|
||||
console.error(error.message)
|
||||
resolve(null)
|
||||
}
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
console.error(`Request for HtmlAttributes.json failed: ${response.statusCode}`)
|
||||
resolve(null)
|
||||
}
|
||||
|
||||
for (let attribute in attributes) {
|
||||
const options = attributes[attribute]
|
||||
if ((options.attribOption != null ? options.attribOption.length : undefined) === 0) { delete options.attribOption }
|
||||
}
|
||||
|
||||
resolve(attributes)
|
||||
})
|
||||
})
|
||||
|
||||
const globalAttributeDescriptionsPromise = fetchGlobalAttributeDescriptions()
|
||||
|
||||
Promise.all([tagsPromise, tagDescriptionsPromise, attributesPromise, globalAttributeDescriptionsPromise]).then((values) => {
|
||||
const tags = values[0]
|
||||
const tagDescriptions = values[1]
|
||||
const attributes = values[2]
|
||||
const attributeDescriptions = values[3]
|
||||
|
||||
for (let tag in tags) {
|
||||
tags[tag].description = tagDescriptions[tag]
|
||||
}
|
||||
|
||||
for (let attribute in attributes) {
|
||||
const options = attributes[attribute]
|
||||
if (options.global) { attributes[attribute].description = attributeDescriptions[attribute] }
|
||||
}
|
||||
|
||||
const completions = {tags, attributes}
|
||||
fs.writeFileSync(path.join(__dirname, 'completions.json'), `${JSON.stringify(completions, null, ' ')}\n`)
|
||||
})
|
1
packages/autocomplete-plus/.coffeelintignore
Normal file
1
packages/autocomplete-plus/.coffeelintignore
Normal file
@ -0,0 +1 @@
|
||||
spec/fixtures
|
3
packages/autocomplete-plus/.gitignore
vendored
Normal file
3
packages/autocomplete-plus/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
npm-debug.log
|
16
packages/autocomplete-plus/.pairs
Normal file
16
packages/autocomplete-plus/.pairs
Normal file
@ -0,0 +1,16 @@
|
||||
pairs:
|
||||
ns: Nathan Sobo; nathan
|
||||
cj: Corey Johnson; cj
|
||||
dg: David Graham; dgraham
|
||||
ks: Kevin Sawicki; kevin
|
||||
jc: Jerry Cheung; jerry
|
||||
bl: Brian Lopez; brian
|
||||
jp: Justin Palmer; justin
|
||||
gt: Garen Torikian; garen
|
||||
mc: Matt Colyer; mcolyer
|
||||
bo: Ben Ogle; benogle
|
||||
jr: Jason Rudolph; jasonrudolph
|
||||
jl: Jessica Lord; jlord
|
||||
email:
|
||||
domain: github.com
|
||||
#global: true
|
109
packages/autocomplete-plus/README.md
Normal file
109
packages/autocomplete-plus/README.md
Normal file
@ -0,0 +1,109 @@
|
||||
# Autocomplete+ package
|
||||
|
||||
Displays possible autocomplete suggestions on keystroke (or manually by typing `ctrl-space`) and inserts a suggestion in the editor if confirmed.
|
||||
|
||||
![autocomplete+](https://cloud.githubusercontent.com/assets/744740/7656861/9fb8bcc4-faea-11e4-9814-9dca218ded93.png)
|
||||
|
||||
[Changelog](https://github.com/atom/autocomplete-plus/releases)
|
||||
|
||||
## Installation
|
||||
|
||||
`autocomplete+` is bundled with Pulsar. You don't have to do anything to install it.
|
||||
|
||||
## Providers
|
||||
|
||||
`autocomplete+` has a powerful autocomplete provider API, allowing provider authors to add language-specific behavior to this package.
|
||||
|
||||
You should *definitely* install additional providers (the default provider bundled with this package is somewhat crude): https://github.com/atom/autocomplete-plus/wiki/Autocomplete-Providers
|
||||
|
||||
## Usage
|
||||
|
||||
Just type some stuff, and autocomplete+ will automatically show you some suggestions.
|
||||
Press `UP` and `DOWN` to select another suggestion, press `TAB` or `ENTER` to confirm your selection. You can change the default keymap in `Preferences`:
|
||||
|
||||
* Keymap For Confirming A Suggestion
|
||||
|
||||
Additionally, the confirm keymap can be customized in your keymap.cson:
|
||||
|
||||
```coffeescript
|
||||
'atom-text-editor.autocomplete-active':
|
||||
'tab': 'unset!'
|
||||
'ctrl-shift-a': 'autocomplete-plus:confirm'
|
||||
```
|
||||
|
||||
If setting custom keybindings, use the `none` setting for the confirmation keymap. All this option does is not set any other keybindings. This allows the `TAB` and `ENTER` keys to be used like normal, without side effects.
|
||||
|
||||
### Remapping Movement Commands
|
||||
|
||||
By default, autocomplete-plus commandeers the editor's core movement commands when the suggestion list is open. You may want to change these movement commands to use your own keybindings.
|
||||
|
||||
First you need to set the `autocomplete-plus.useCoreMovementCommands` setting to `false`, which you can do from the `autocomplete-plus` settings in the settings view.
|
||||
|
||||
![core-movement](https://cloud.githubusercontent.com/assets/69169/8839134/72a9c7e6-3087-11e5-9d1f-8d3d15961327.jpg)
|
||||
|
||||
Or by adding this to your config file:
|
||||
|
||||
```coffee
|
||||
"*":
|
||||
"autocomplete-plus":
|
||||
"useCoreMovementCommands": false
|
||||
```
|
||||
|
||||
Then add these to your keymap file:
|
||||
|
||||
```coffeescript
|
||||
'body atom-text-editor.autocomplete-active':
|
||||
'ctrl-p': 'autocomplete-plus:move-up'
|
||||
'ctrl-n': 'autocomplete-plus:move-down'
|
||||
'pageup': 'autocomplete-plus:page-up'
|
||||
'pagedown': 'autocomplete-plus:page-down'
|
||||
'home': 'autocomplete-plus:move-to-top'
|
||||
'end': 'autocomplete-plus:move-to-bottom'
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
* Shows suggestions while typing
|
||||
* Includes a default provider (`SymbolProvider`):
|
||||
* Wordlist generation happens when you open a file, while editing the file, and on save
|
||||
* Suggestions are calculated using `fuzzaldrin`
|
||||
* Exposes a provider API which can be used to extend the functionality of the package and provide targeted / contextually correct suggestions
|
||||
* Disable autocomplete for file(s) via blacklisting, e.g. `*.md` to blacklist Markdown files
|
||||
* Disable autocomplete for editor scope(s) via blacklisting
|
||||
* Expands a snippet if an autocomplete+ provider includes one in a suggestion
|
||||
* Allows external editors to register for autocompletions
|
||||
|
||||
## Provider API
|
||||
|
||||
Great autocomplete depends on having great autocomplete providers. If there is not already a great provider for the language / grammar that you are working in, please consider creating a provider.
|
||||
|
||||
[Read the `Provider API` documentation](https://github.com/atom/autocomplete-plus/wiki/Provider-API) to learn how to create a new autocomplete provider.
|
||||
|
||||
## `SymbolProvider` Configuration
|
||||
|
||||
If the default `SymbolProvider` is missing useful information for the language / grammar you're working with, please take a look at the [`SymbolProvider` Config API](https://github.com/atom/autocomplete-plus/wiki/SymbolProvider-Config-API).
|
||||
|
||||
## The `watchEditor` API
|
||||
|
||||
The `watchEditor` method on the `AutocompleteManager` object is exposed as a [provided service](http://flight-manual.atom.io/behind-atom/sections/interacting-with-other-packages-via-services/), named `autocomplete.watchEditor`. The method allows external editors to register for autocompletions from providers with a given set of labels. Disposing the returned object will undo this request. External packages can access this service with the following code.
|
||||
|
||||
In `package.json`:
|
||||
```
|
||||
{
|
||||
"consumedServices": {
|
||||
"autocomplete.watchEditor": {
|
||||
"versions": {
|
||||
"1.0.0": "consumeAutocompleteWatchEditor"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
In the main module file:
|
||||
```
|
||||
consumeAutocompleteWatchEditor(watchEditor) {
|
||||
this.autocompleteDisposable = watchEditor(
|
||||
this.editor, ['symbol-provider']
|
||||
)
|
||||
}
|
||||
```
|
37
packages/autocomplete-plus/coffeelint.json
Normal file
37
packages/autocomplete-plus/coffeelint.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"max_line_length": {
|
||||
"level": "ignore"
|
||||
},
|
||||
"no_empty_param_list": {
|
||||
"level": "error"
|
||||
},
|
||||
"arrow_spacing": {
|
||||
"level": "error"
|
||||
},
|
||||
"no_interpolation_in_single_quotes": {
|
||||
"level": "error"
|
||||
},
|
||||
"no_debugger": {
|
||||
"level": "error"
|
||||
},
|
||||
"prefer_english_operator": {
|
||||
"level": "error"
|
||||
},
|
||||
"colon_assignment_spacing": {
|
||||
"spacing": {
|
||||
"left": 0,
|
||||
"right": 1
|
||||
},
|
||||
"level": "error"
|
||||
},
|
||||
"braces_spacing": {
|
||||
"spaces": 0,
|
||||
"level": "error"
|
||||
},
|
||||
"spacing_after_comma": {
|
||||
"level": "error"
|
||||
},
|
||||
"no_stand_alone_at": {
|
||||
"level": "error"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
'atom-text-editor':
|
||||
'ctrl-space': 'autocomplete-plus:activate'
|
||||
|
||||
'atom-text-editor.autocomplete-active':
|
||||
'escape': 'autocomplete-plus:cancel'
|
||||
'f1': 'autocomplete-plus:navigate-to-description-more-link'
|
799
packages/autocomplete-plus/lib/autocomplete-manager.js
Normal file
799
packages/autocomplete-plus/lib/autocomplete-manager.js
Normal file
@ -0,0 +1,799 @@
|
||||
const {CompositeDisposable, Disposable, Point, Range} = require('atom')
|
||||
const path = require('path')
|
||||
const fuzzaldrin = require('fuzzaldrin')
|
||||
const fuzzaldrinPlus = require('fuzzaldrin-plus')
|
||||
|
||||
const ProviderManager = require('./provider-manager')
|
||||
const SuggestionList = require('./suggestion-list')
|
||||
const {UnicodeLetters} = require('./unicode-helpers')
|
||||
const getAdditionalWordCharacters = require('./get-additional-word-characters')
|
||||
|
||||
const MAX_LEGACY_PREFIX_LENGTH = 80
|
||||
const wordCharacterRegexCache = new Map()
|
||||
|
||||
// Deferred requires
|
||||
let minimatch = null
|
||||
let grim = null
|
||||
|
||||
module.exports =
|
||||
class AutocompleteManager {
|
||||
constructor () {
|
||||
this.autosaveEnabled = false
|
||||
this.backspaceTriggersAutocomplete = true
|
||||
this.autoConfirmSingleSuggestionEnabled = true
|
||||
this.bracketMatcherPairs = ['()', '[]', '{}', '""', "''", '``', '“”', '‘’', '«»', '‹›']
|
||||
this.buffer = null
|
||||
this.compositionInProgress = false
|
||||
this.disposed = false
|
||||
this.editor = null
|
||||
this.editorLabels = null
|
||||
this.editorSubscriptions = null
|
||||
this.editorView = null
|
||||
this.providerManager = null
|
||||
this.ready = false
|
||||
this.subscriptions = null
|
||||
this.suggestionList = null
|
||||
this.suppressForClasses = []
|
||||
this.shouldDisplaySuggestions = false
|
||||
this.prefixRegex = null
|
||||
this.wordPrefixRegex = null
|
||||
this.updateCurrentEditor = this.updateCurrentEditor.bind(this)
|
||||
this.handleCommands = this.handleCommands.bind(this)
|
||||
this.findSuggestions = this.findSuggestions.bind(this)
|
||||
this.getSuggestionsFromProviders = this.getSuggestionsFromProviders.bind(this)
|
||||
this.displaySuggestions = this.displaySuggestions.bind(this)
|
||||
this.hideSuggestionList = this.hideSuggestionList.bind(this)
|
||||
|
||||
this.showOrHideSuggestionListForBufferChanges = this.showOrHideSuggestionListForBufferChanges.bind(this)
|
||||
this.providerManager = new ProviderManager()
|
||||
this.suggestionList = new SuggestionList()
|
||||
this.watchedEditors = new WeakSet()
|
||||
}
|
||||
|
||||
initialize () {
|
||||
this.subscriptions = new CompositeDisposable()
|
||||
|
||||
this.providerManager.initialize()
|
||||
this.suggestionList.initialize()
|
||||
|
||||
this.subscriptions.add(atom.config.observe('autocomplete-plus.enableExtendedUnicodeSupport', enableExtendedUnicodeSupport => {
|
||||
if (enableExtendedUnicodeSupport) {
|
||||
this.prefixRegex = new RegExp(`(['"~\`!@#\\$%^&*\\(\\)\\{\\}\\[\\]=+,/\\?>])?(([${UnicodeLetters}\\d_]+[${UnicodeLetters}\\d_-]*)|([.:;[{(< ]+))$`)
|
||||
this.wordPrefixRegex = new RegExp(`^[${UnicodeLetters}\\d_]+[${UnicodeLetters}\\d_-]*$`)
|
||||
} else {
|
||||
this.prefixRegex = /(\b|['"~`!@#$%^&*(){}[\]=+,/?>])((\w+[\w-]*)|([.:;[{(< ]+))$/
|
||||
this.wordPrefixRegex = /^\w+[\w-]*$/
|
||||
}
|
||||
}
|
||||
))
|
||||
this.subscriptions.add(this.providerManager)
|
||||
this.handleEvents()
|
||||
this.handleCommands()
|
||||
this.subscriptions.add(this.suggestionList) // We're adding this last so it is disposed after events
|
||||
this.ready = true
|
||||
}
|
||||
|
||||
setSnippetsManager (snippetsManager) {
|
||||
this.snippetsManager = snippetsManager
|
||||
}
|
||||
|
||||
updateCurrentEditor (currentEditor, labels) {
|
||||
if (currentEditor === this.editor) { return }
|
||||
if (this.editorSubscriptions) {
|
||||
this.editorSubscriptions.dispose()
|
||||
}
|
||||
this.editorSubscriptions = null
|
||||
|
||||
// Stop tracking editor + buffer
|
||||
this.editor = null
|
||||
this.editorView = null
|
||||
this.buffer = null
|
||||
this.isCurrentFileBlackListedCache = null
|
||||
|
||||
if (!this.editorIsValid(currentEditor)) { return }
|
||||
|
||||
// Track the new editor, editorView, and buffer and set
|
||||
// the labels for its providers.
|
||||
this.editor = currentEditor
|
||||
this.editorLabels = labels
|
||||
this.editorView = atom.views.getView(this.editor)
|
||||
this.buffer = this.editor.getBuffer()
|
||||
|
||||
this.editorSubscriptions = new CompositeDisposable()
|
||||
|
||||
// Subscribe to buffer events:
|
||||
this.editorSubscriptions.add(this.buffer.onDidSave((e) => { this.bufferSaved(e) }))
|
||||
this.editorSubscriptions.add(this.buffer.onDidChangeText(this.showOrHideSuggestionListForBufferChanges))
|
||||
|
||||
// Watch IME Events To Allow IME To Function Without The Suggestion List Showing
|
||||
const compositionStart = () => {
|
||||
this.compositionInProgress = true
|
||||
}
|
||||
const compositionEnd = () => {
|
||||
this.compositionInProgress = false
|
||||
}
|
||||
|
||||
this.editorView.addEventListener('compositionstart', compositionStart)
|
||||
this.editorView.addEventListener('compositionend', compositionEnd)
|
||||
this.editorSubscriptions.add(new Disposable(() => {
|
||||
if (this.editorView) {
|
||||
this.editorView.removeEventListener('compositionstart', compositionStart)
|
||||
this.editorView.removeEventListener('compositionend', compositionEnd)
|
||||
}
|
||||
}))
|
||||
|
||||
// Subscribe to editor events:
|
||||
// Close the overlay when the cursor moved without changing any text
|
||||
this.editorSubscriptions.add(this.editor.onDidChangeCursorPosition((e) => { this.cursorMoved(e) }))
|
||||
return this.editorSubscriptions.add(this.editor.onDidChangePath(() => {
|
||||
this.isCurrentFileBlackListedCache = null
|
||||
}))
|
||||
}
|
||||
|
||||
editorIsValid (editor) {
|
||||
// TODO: remove conditional when `isTextEditor` is shipped.
|
||||
if (typeof atom.workspace.isTextEditor === 'function') {
|
||||
return atom.workspace.isTextEditor(editor)
|
||||
} else {
|
||||
if (!editor) { return false }
|
||||
// Should we disqualify TextEditors with the Grammar text.plain.null-grammar?
|
||||
return (editor.getText != null)
|
||||
}
|
||||
}
|
||||
|
||||
// Makes the autocomplete manager watch the `editor`.
|
||||
// When the watched `editor` is focused, it will provide autocompletions from
|
||||
// providers with the given `labels`.
|
||||
//
|
||||
// Returns a {Disposable} to stop watching the `editor`.
|
||||
watchEditor (editor, labels) {
|
||||
if (this.watchedEditors.has(editor)) return
|
||||
|
||||
let view = atom.views.getView(editor)
|
||||
|
||||
if (view.hasFocus()) {
|
||||
this.updateCurrentEditor(editor, labels)
|
||||
}
|
||||
|
||||
let focusListener = (element) => this.updateCurrentEditor(editor, labels)
|
||||
view.addEventListener('focus', focusListener)
|
||||
let blurListener = (element) => this.hideSuggestionList()
|
||||
view.addEventListener('blur', blurListener)
|
||||
|
||||
let disposable = new Disposable(() => {
|
||||
view.removeEventListener('focus', focusListener)
|
||||
view.removeEventListener('blur', blurListener)
|
||||
if (this.editor === editor) {
|
||||
this.updateCurrentEditor(null)
|
||||
}
|
||||
})
|
||||
this.watchedEditors.add(editor)
|
||||
this.subscriptions.add(disposable)
|
||||
return new Disposable(() => {
|
||||
disposable.dispose()
|
||||
if (this.subscriptions != null) {
|
||||
this.subscriptions.remove(disposable)
|
||||
}
|
||||
this.watchedEditors.delete(editor)
|
||||
})
|
||||
}
|
||||
|
||||
handleEvents () {
|
||||
this.subscriptions.add(atom.workspace.observeTextEditors((editor) => {
|
||||
const disposable = this.watchEditor(editor, ['workspace-center'])
|
||||
editor.onDidDestroy(() => disposable.dispose())
|
||||
}))
|
||||
|
||||
// Watch config values
|
||||
this.subscriptions.add(atom.config.observe('autosave.enabled', (value) => { this.autosaveEnabled = value }))
|
||||
this.subscriptions.add(atom.config.observe('autocomplete-plus.backspaceTriggersAutocomplete', (value) => { this.backspaceTriggersAutocomplete = value }))
|
||||
this.subscriptions.add(atom.config.observe('autocomplete-plus.enableAutoActivation', (value) => { this.autoActivationEnabled = value }))
|
||||
this.subscriptions.add(atom.config.observe('autocomplete-plus.enableAutoConfirmSingleSuggestion', (value) => { this.autoConfirmSingleSuggestionEnabled = value }))
|
||||
this.subscriptions.add(atom.config.observe('autocomplete-plus.consumeSuffix', (value) => { this.consumeSuffix = value }))
|
||||
this.subscriptions.add(atom.config.observe('autocomplete-plus.useAlternateScoring', (value) => { this.useAlternateScoring = value }))
|
||||
this.subscriptions.add(atom.config.observe('autocomplete-plus.fileBlacklist', (value) => {
|
||||
if (value) {
|
||||
this.fileBlacklist = value.map((s) => { return s.trim() })
|
||||
}
|
||||
this.isCurrentFileBlackListedCache = null
|
||||
}))
|
||||
this.subscriptions.add(atom.config.observe('autocomplete-plus.suppressActivationForEditorClasses', value => {
|
||||
this.suppressForClasses = []
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const selector = value[i]
|
||||
const classes = (selector.trim().split('.').filter((className) => className.trim()).map((className) => className.trim()))
|
||||
if (classes.length) { this.suppressForClasses.push(classes) }
|
||||
}
|
||||
}))
|
||||
|
||||
// Handle events from suggestion list
|
||||
this.subscriptions.add(this.suggestionList.onDidConfirm((e) => { this.confirm(e) }))
|
||||
this.subscriptions.add(this.suggestionList.onDidCancel(this.hideSuggestionList))
|
||||
this.subscriptions.add(this.suggestionList.onDidSelect(suggestion => { this.getDetailsOnSelect(suggestion) }))
|
||||
}
|
||||
|
||||
handleCommands () {
|
||||
return this.subscriptions.add(atom.commands.add('atom-text-editor', {
|
||||
'autocomplete-plus:activate': (event) => {
|
||||
this.shouldDisplaySuggestions = true
|
||||
let activatedManually = true
|
||||
if (event.detail && event.detail.activatedManually !== null && typeof event.detail.activatedManually !== 'undefined') {
|
||||
activatedManually = event.detail.activatedManually
|
||||
}
|
||||
this.findSuggestions(activatedManually)
|
||||
},
|
||||
'autocomplete-plus:navigate-to-description-more-link': () => {
|
||||
let suggestionListView = atom.views.getView(this.editor)
|
||||
let descriptionContainer = suggestionListView.querySelector('.suggestion-description')
|
||||
if (descriptionContainer !== null && descriptionContainer.style.display === 'block') {
|
||||
let descriptionMoreLink = descriptionContainer.querySelector('.suggestion-description-more-link')
|
||||
require('electron').shell.openExternal(descriptionMoreLink.href)
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
// Private: Finds suggestions for the current prefix, sets the list items,
|
||||
// positions the overlay and shows it
|
||||
findSuggestions (activatedManually) {
|
||||
if (this.disposed) { return }
|
||||
if ((this.providerManager == null) || (this.editor == null) || (this.buffer == null)) { return }
|
||||
if (this.isCurrentFileBlackListed()) { return }
|
||||
const cursor = this.editor.getLastCursor()
|
||||
if (cursor == null) { return }
|
||||
|
||||
const bufferPosition = cursor.getBufferPosition()
|
||||
const scopeDescriptor = cursor.getScopeDescriptor()
|
||||
const prefix = this.getPrefix(this.editor, bufferPosition, scopeDescriptor) // Passed to providers with API version >= 4.0.0
|
||||
const legacyPrefix = this.getLegacyPrefix(this.editor, bufferPosition) // Passed to providers with API version < 4.0.0
|
||||
|
||||
return this.getSuggestionsFromProviders({editor: this.editor, bufferPosition, scopeDescriptor, prefix, legacyPrefix, activatedManually})
|
||||
}
|
||||
|
||||
getSuggestionsFromProviders (options) {
|
||||
let suggestionsPromise
|
||||
const providers = this.providerManager.applicableProviders(this.editorLabels, options.scopeDescriptor)
|
||||
|
||||
const providerPromises = []
|
||||
providers.forEach(provider => {
|
||||
const apiVersion = this.providerManager.apiVersionForProvider(provider)
|
||||
|
||||
let getSuggestions
|
||||
let upgradedOptions
|
||||
|
||||
if (apiVersion === 1) {
|
||||
getSuggestions = provider.requestHandler.bind(provider)
|
||||
upgradedOptions = {
|
||||
editor: options.editor,
|
||||
prefix: options.prefix,
|
||||
bufferPosition: options.bufferPosition,
|
||||
position: options.bufferPosition,
|
||||
scope: options.scopeDescriptor,
|
||||
scopeChain: options.scopeDescriptor.getScopeChain(),
|
||||
buffer: options.editor.getBuffer(),
|
||||
cursor: options.editor.getLastCursor()
|
||||
}
|
||||
} else {
|
||||
getSuggestions = provider.getSuggestions.bind(provider)
|
||||
if (apiVersion < 4) {
|
||||
upgradedOptions = Object.assign({}, options)
|
||||
upgradedOptions.prefix = options.legacyPrefix
|
||||
} else {
|
||||
upgradedOptions = Object.assign({}, options)
|
||||
delete upgradedOptions.legacyPrefix
|
||||
}
|
||||
}
|
||||
|
||||
return providerPromises.push(Promise.resolve(getSuggestions(upgradedOptions)).then(providerSuggestions => {
|
||||
if (providerSuggestions == null) { return }
|
||||
|
||||
// TODO API: remove upgrading when 1.0 support is removed
|
||||
let hasDeprecations = false
|
||||
if (apiVersion > 1 && providerSuggestions.length) {
|
||||
hasDeprecations = this.deprecateForSuggestion(provider, providerSuggestions[0])
|
||||
}
|
||||
|
||||
if (hasDeprecations || apiVersion === 1) {
|
||||
providerSuggestions = providerSuggestions.map((suggestion) => {
|
||||
const newSuggestion = {
|
||||
text: suggestion.text != null ? suggestion.text : suggestion.word,
|
||||
snippet: suggestion.snippet,
|
||||
replacementPrefix: suggestion.replacementPrefix != null ? suggestion.replacementPrefix : suggestion.prefix,
|
||||
className: suggestion.className,
|
||||
type: suggestion.type
|
||||
}
|
||||
if ((newSuggestion.rightLabelHTML == null) && suggestion.renderLabelAsHtml) { newSuggestion.rightLabelHTML = suggestion.label }
|
||||
if ((newSuggestion.rightLabel == null) && !suggestion.renderLabelAsHtml) { newSuggestion.rightLabel = suggestion.label }
|
||||
return newSuggestion
|
||||
})
|
||||
}
|
||||
|
||||
let hasEmpty = false // Optimization: only create another array when there are empty items
|
||||
for (let i = 0; i < providerSuggestions.length; i++) {
|
||||
const suggestion = providerSuggestions[i]
|
||||
if (!suggestion.snippet && !suggestion.text) { hasEmpty = true }
|
||||
// Suggestions are mutable and are updated with a new replacement prefix. In order to
|
||||
// distinguish between suggestion that had original prefix and assigned one, we use
|
||||
// `isPrefixModified` flag. If it is `true`, we reset replacement prefix.
|
||||
if (suggestion.replacementPrefix == null || !!suggestion.isPrefixModified) {
|
||||
if (apiVersion < 4) {
|
||||
suggestion.replacementPrefix = this.wordPrefixRegex.test(options.prefix) ? options.prefix : ''
|
||||
} else {
|
||||
suggestion.replacementPrefix = options.prefix
|
||||
}
|
||||
suggestion.isPrefixModified = true
|
||||
}
|
||||
suggestion.provider = provider
|
||||
}
|
||||
|
||||
if (hasEmpty) {
|
||||
const res = []
|
||||
for (const s of providerSuggestions) {
|
||||
if (s.snippet || s.text) {
|
||||
res.push(s)
|
||||
}
|
||||
}
|
||||
providerSuggestions = res
|
||||
}
|
||||
|
||||
if (provider.filterSuggestions) {
|
||||
providerSuggestions = this.filterSuggestions(providerSuggestions, options)
|
||||
}
|
||||
return providerSuggestions
|
||||
}))
|
||||
})
|
||||
|
||||
if (!providerPromises || !providerPromises.length) {
|
||||
return
|
||||
}
|
||||
|
||||
suggestionsPromise = Promise.all(providerPromises)
|
||||
this.currentSuggestionsPromise = suggestionsPromise
|
||||
return this.currentSuggestionsPromise
|
||||
.then(this.mergeSuggestionsFromProviders)
|
||||
.then(suggestions => {
|
||||
if (this.currentSuggestionsPromise !== suggestionsPromise) { return }
|
||||
if (options.activatedManually && this.shouldDisplaySuggestions && this.autoConfirmSingleSuggestionEnabled && suggestions.length === 1) {
|
||||
// When there is one suggestion in manual mode, just confirm it
|
||||
return this.confirm(suggestions[0])
|
||||
} else {
|
||||
return this.displaySuggestions(suggestions, options)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
filterSuggestions (suggestions, {prefix}) {
|
||||
const results = []
|
||||
const fuzzaldrinProvider = this.useAlternateScoring ? fuzzaldrinPlus : fuzzaldrin
|
||||
for (let i = 0; i < suggestions.length; i++) {
|
||||
// sortScore mostly preserves in the original sorting. The function is
|
||||
// chosen such that suggestions with a very high match score can break out.
|
||||
let score
|
||||
const suggestion = suggestions[i]
|
||||
suggestion.sortScore = Math.max((-i / 10) + 3, 0) + 1
|
||||
suggestion.score = null
|
||||
|
||||
const text = (suggestion.snippet || suggestion.text)
|
||||
const suggestionPrefix = suggestion.replacementPrefix != null ? suggestion.replacementPrefix : prefix
|
||||
const prefixIsEmpty = !suggestionPrefix || suggestionPrefix === ' '
|
||||
const firstCharIsMatch = !prefixIsEmpty && suggestionPrefix[0].toLowerCase() === text[0].toLowerCase()
|
||||
|
||||
if (prefixIsEmpty) {
|
||||
results.push(suggestion)
|
||||
}
|
||||
if (firstCharIsMatch && (score = fuzzaldrinProvider.score(text, suggestionPrefix)) > 0) {
|
||||
suggestion.score = score * suggestion.sortScore
|
||||
results.push(suggestion)
|
||||
}
|
||||
}
|
||||
|
||||
results.sort(this.reverseSortOnScoreComparator)
|
||||
return results
|
||||
}
|
||||
|
||||
reverseSortOnScoreComparator (a, b) {
|
||||
let bscore = b.score
|
||||
if (!bscore) {
|
||||
bscore = b.sortScore
|
||||
}
|
||||
let ascore = a.score
|
||||
if (!ascore) {
|
||||
ascore = b.sortScore
|
||||
}
|
||||
return bscore - ascore
|
||||
}
|
||||
|
||||
// providerSuggestions - array of arrays of suggestions provided by all called providers
|
||||
mergeSuggestionsFromProviders (providerSuggestions) {
|
||||
return providerSuggestions.reduce((suggestions, providerSuggestions) => {
|
||||
if (providerSuggestions && providerSuggestions.length) {
|
||||
suggestions = suggestions.concat(providerSuggestions)
|
||||
}
|
||||
|
||||
return suggestions
|
||||
}, [])
|
||||
}
|
||||
|
||||
deprecateForSuggestion (provider, suggestion) {
|
||||
let hasDeprecations = false
|
||||
if (suggestion.word != null) {
|
||||
hasDeprecations = true
|
||||
if (typeof grim === 'undefined' || grim === null) { grim = require('grim') }
|
||||
grim.deprecate(`Autocomplete provider '${provider.constructor.name}(${provider.id})'
|
||||
returns suggestions with a \`word\` attribute.
|
||||
The \`word\` attribute is now \`text\`.
|
||||
See https://github.com/atom/autocomplete-plus/wiki/Provider-API`
|
||||
)
|
||||
}
|
||||
if (suggestion.prefix != null) {
|
||||
hasDeprecations = true
|
||||
if (typeof grim === 'undefined' || grim === null) { grim = require('grim') }
|
||||
grim.deprecate(`Autocomplete provider '${provider.constructor.name}(${provider.id})'
|
||||
returns suggestions with a \`prefix\` attribute.
|
||||
The \`prefix\` attribute is now \`replacementPrefix\` and is optional.
|
||||
See https://github.com/atom/autocomplete-plus/wiki/Provider-API`
|
||||
)
|
||||
}
|
||||
if (suggestion.label != null) {
|
||||
hasDeprecations = true
|
||||
if (typeof grim === 'undefined' || grim === null) { grim = require('grim') }
|
||||
grim.deprecate(`Autocomplete provider '${provider.constructor.name}(${provider.id})'
|
||||
returns suggestions with a \`label\` attribute.
|
||||
The \`label\` attribute is now \`rightLabel\` or \`rightLabelHTML\`.
|
||||
See https://github.com/atom/autocomplete-plus/wiki/Provider-API`
|
||||
)
|
||||
}
|
||||
if (suggestion.onWillConfirm != null) {
|
||||
hasDeprecations = true
|
||||
if (typeof grim === 'undefined' || grim === null) { grim = require('grim') }
|
||||
grim.deprecate(`Autocomplete provider '${provider.constructor.name}(${provider.id})'
|
||||
returns suggestions with a \`onWillConfirm\` callback.
|
||||
The \`onWillConfirm\` callback is no longer supported.
|
||||
See https://github.com/atom/autocomplete-plus/wiki/Provider-API`
|
||||
)
|
||||
}
|
||||
if (suggestion.onDidConfirm != null) {
|
||||
hasDeprecations = true
|
||||
if (typeof grim === 'undefined' || grim === null) { grim = require('grim') }
|
||||
grim.deprecate(`Autocomplete provider '${provider.constructor.name}(${provider.id})'
|
||||
returns suggestions with a \`onDidConfirm\` callback.
|
||||
The \`onDidConfirm\` callback is now a \`onDidInsertSuggestion\` callback on the provider itself.
|
||||
See https://github.com/atom/autocomplete-plus/wiki/Provider-API`
|
||||
)
|
||||
}
|
||||
return hasDeprecations
|
||||
}
|
||||
|
||||
displaySuggestions (suggestions, options) {
|
||||
switch (atom.config.get('autocomplete-plus.similarSuggestionRemoval')) {
|
||||
case 'textOrSnippet': {
|
||||
suggestions = this.getUniqueSuggestions(suggestions, (suggestion) => suggestion.text + suggestion.snippet)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (this.shouldDisplaySuggestions && suggestions.length) {
|
||||
return this.showSuggestionList(suggestions, options)
|
||||
} else {
|
||||
return this.hideSuggestionList()
|
||||
}
|
||||
}
|
||||
|
||||
getUniqueSuggestions (suggestions, uniqueKeyFunction) {
|
||||
const seen = {}
|
||||
const result = []
|
||||
for (let i = 0; i < suggestions.length; i++) {
|
||||
const suggestion = suggestions[i]
|
||||
const val = uniqueKeyFunction(suggestion)
|
||||
if (!seen[val]) {
|
||||
result.push(suggestion)
|
||||
seen[val] = true
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
getPrefix (editor, position, scopeDescriptor) {
|
||||
const wordCharacterRegex = this.getWordCharacterRegex(scopeDescriptor)
|
||||
const line = editor.getBuffer().getTextInRange([[position.row, 0], position])
|
||||
|
||||
let startColumn = position.column
|
||||
while (startColumn > 0) {
|
||||
let prevChar = line[startColumn - 1]
|
||||
if (wordCharacterRegex.test(prevChar)) {
|
||||
startColumn--
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return line.slice(startColumn)
|
||||
}
|
||||
|
||||
getWordCharacterRegex (scopeDescriptor) {
|
||||
const additionalWordChars = getAdditionalWordCharacters(scopeDescriptor)
|
||||
let regex = wordCharacterRegexCache.get(additionalWordChars)
|
||||
|
||||
if (!regex) {
|
||||
regex = new RegExp(`[${UnicodeLetters}${additionalWordChars.replace(']', '\\]')}\\d]`)
|
||||
wordCharacterRegexCache.set(additionalWordChars, regex)
|
||||
}
|
||||
return regex
|
||||
}
|
||||
|
||||
getLegacyPrefix (editor, bufferPosition) {
|
||||
const {row, column} = bufferPosition
|
||||
const line = editor.getTextInRange(new Range(
|
||||
new Point(row, Math.max(0, column - MAX_LEGACY_PREFIX_LENGTH)),
|
||||
bufferPosition
|
||||
))
|
||||
const prefix = this.prefixRegex.exec(line)
|
||||
if (!prefix || !prefix[2] || prefix[2].length === MAX_LEGACY_PREFIX_LENGTH) return ''
|
||||
return prefix[2]
|
||||
}
|
||||
|
||||
// Private: Gets called when the user successfully confirms a suggestion
|
||||
//
|
||||
// match - An {Object} representing the confirmed suggestion
|
||||
confirm (suggestion) {
|
||||
if ((this.editor == null) || (suggestion == null) || !!this.disposed) { return }
|
||||
|
||||
const apiVersion = this.providerManager.apiVersionForProvider(suggestion.provider)
|
||||
const triggerPosition = this.editor.getLastCursor().getBufferPosition()
|
||||
|
||||
// TODO API: Remove as this is no longer used
|
||||
if (suggestion.onWillConfirm) {
|
||||
suggestion.onWillConfirm()
|
||||
}
|
||||
|
||||
const selections = this.editor.getSelections()
|
||||
if (selections && selections.length) {
|
||||
for (const s of selections) {
|
||||
if (s && s.clear) {
|
||||
s.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.hideSuggestionList()
|
||||
|
||||
this.replaceTextWithMatch(suggestion)
|
||||
|
||||
if (apiVersion > 1) {
|
||||
if (suggestion.provider && suggestion.provider.onDidInsertSuggestion) {
|
||||
suggestion.provider.onDidInsertSuggestion({editor: this.editor, suggestion, triggerPosition})
|
||||
}
|
||||
} else {
|
||||
if (suggestion.onDidConfirm) {
|
||||
suggestion.onDidConfirm()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getDetailsOnSelect (suggestion) {
|
||||
if (suggestion != null && suggestion.provider && suggestion.provider.getSuggestionDetailsOnSelect) {
|
||||
Promise.resolve(suggestion.provider.getSuggestionDetailsOnSelect(suggestion))
|
||||
.then(detailedSuggestion => {
|
||||
this.suggestionList.replaceItem(suggestion, detailedSuggestion)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
showSuggestionList (suggestions, options) {
|
||||
if (this.disposed) { return }
|
||||
this.suggestionList.changeItems(suggestions)
|
||||
return this.suggestionList.show(this.editor, options)
|
||||
}
|
||||
|
||||
hideSuggestionList () {
|
||||
if (this.disposed) { return }
|
||||
this.suggestionList.changeItems(null)
|
||||
this.suggestionList.hide()
|
||||
this.shouldDisplaySuggestions = false
|
||||
}
|
||||
|
||||
requestHideSuggestionList (command) {
|
||||
if (this.hideTimeout == null) {
|
||||
this.hideTimeout = setTimeout(() => {
|
||||
this.hideSuggestionList()
|
||||
this.hideTimeout = null
|
||||
}, 0)
|
||||
}
|
||||
this.shouldDisplaySuggestions = false
|
||||
}
|
||||
|
||||
cancelHideSuggestionListRequest () {
|
||||
clearTimeout(this.hideTimeout)
|
||||
this.hideTimeout = null
|
||||
}
|
||||
|
||||
// Private: Replaces the current prefix with the given match.
|
||||
//
|
||||
// match - The match to replace the current prefix with
|
||||
replaceTextWithMatch (suggestion) {
|
||||
if (this.editor == null) { return }
|
||||
|
||||
const cursors = this.editor.getCursors()
|
||||
if (cursors == null) { return }
|
||||
|
||||
return this.editor.transact(() => {
|
||||
for (let i = 0; i < cursors.length; i++) {
|
||||
const cursor = cursors[i]
|
||||
const endPosition = cursor.getBufferPosition()
|
||||
const beginningPosition = [endPosition.row, endPosition.column - suggestion.replacementPrefix.length]
|
||||
|
||||
if (this.editor.getTextInBufferRange([beginningPosition, endPosition]) === suggestion.replacementPrefix) {
|
||||
const suffix = this.consumeSuffix ? this.getSuffix(this.editor, endPosition, suggestion) : ''
|
||||
if (suffix.length) { cursor.moveRight(suffix.length) }
|
||||
cursor.selection.selectLeft(suggestion.replacementPrefix.length + suffix.length)
|
||||
|
||||
if ((suggestion.snippet != null) && (this.snippetsManager != null)) {
|
||||
this.snippetsManager.insertSnippet(suggestion.snippet, this.editor, cursor)
|
||||
} else {
|
||||
cursor.selection.insertText(suggestion.text != null ? suggestion.text : suggestion.snippet, {
|
||||
autoIndentNewline: this.editor.shouldAutoIndent(),
|
||||
autoDecreaseIndent: this.editor.shouldAutoIndent()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
getSuffix (editor, bufferPosition, suggestion) {
|
||||
// This just chews through the suggestion and tries to match the suggestion
|
||||
// substring with the lineText starting at the cursor. There is probably a
|
||||
// more efficient way to do this.
|
||||
let suffix = (suggestion.snippet != null ? suggestion.snippet : suggestion.text)
|
||||
const endPosition = [bufferPosition.row, bufferPosition.column + suffix.length]
|
||||
const endOfLineText = editor.getTextInBufferRange([bufferPosition, endPosition])
|
||||
const nonWordCharacters = new Set(atom.config.get('editor.nonWordCharacters').split(''))
|
||||
while (suffix) {
|
||||
if (endOfLineText.startsWith(suffix) && !nonWordCharacters.has(suffix[0])) { break }
|
||||
suffix = suffix.slice(1)
|
||||
}
|
||||
return suffix
|
||||
}
|
||||
|
||||
// Private: Checks whether the current file is blacklisted.
|
||||
//
|
||||
// Returns {Boolean} that defines whether the current file is blacklisted
|
||||
isCurrentFileBlackListed () {
|
||||
// minimatch is slow. Not necessary to do this computation on every request for suggestions
|
||||
let left
|
||||
if (this.isCurrentFileBlackListedCache != null) { return this.isCurrentFileBlackListedCache }
|
||||
|
||||
if ((this.fileBlacklist == null) || this.fileBlacklist.length === 0) {
|
||||
this.isCurrentFileBlackListedCache = false
|
||||
return this.isCurrentFileBlackListedCache
|
||||
}
|
||||
|
||||
if (typeof minimatch === 'undefined' || minimatch === null) { minimatch = require('minimatch') }
|
||||
const fileName = path.basename((left = this.buffer.getPath()) != null ? left : '')
|
||||
for (let i = 0; i < this.fileBlacklist.length; i++) {
|
||||
const blacklistGlob = this.fileBlacklist[i]
|
||||
if (minimatch(fileName, blacklistGlob)) {
|
||||
this.isCurrentFileBlackListedCache = true
|
||||
return this.isCurrentFileBlackListedCache
|
||||
}
|
||||
}
|
||||
|
||||
this.isCurrentFileBlackListedCache = false
|
||||
return this.isCurrentFileBlackListedCache
|
||||
}
|
||||
|
||||
// Private: Gets called when the content has been modified
|
||||
requestNewSuggestions () {
|
||||
let delay = atom.config.get('autocomplete-plus.autoActivationDelay')
|
||||
|
||||
if (this.delayTimeout != null) {
|
||||
clearTimeout(this.delayTimeout)
|
||||
}
|
||||
|
||||
if (delay) {
|
||||
this.delayTimeout = setTimeout(this.findSuggestions, delay)
|
||||
} else {
|
||||
this.findSuggestions()
|
||||
}
|
||||
|
||||
this.shouldDisplaySuggestions = true
|
||||
}
|
||||
|
||||
cancelNewSuggestionsRequest () {
|
||||
if (this.delayTimeout != null) {
|
||||
clearTimeout(this.delayTimeout)
|
||||
}
|
||||
this.shouldDisplaySuggestions = false
|
||||
}
|
||||
|
||||
// Private: Gets called when the cursor has moved. Cancels the autocompletion if
|
||||
// the text has not been changed.
|
||||
//
|
||||
// data - An {Object} containing information on why the cursor has been moved
|
||||
cursorMoved ({textChanged}) {
|
||||
// The delay is a workaround for the backspace case. The way atom implements
|
||||
// backspace is to select left 1 char, then delete. This results in a
|
||||
// cursorMoved event with textChanged == false. So we delay, and if the
|
||||
// bufferChanged handler decides to show suggestions, it will cancel the
|
||||
// hideSuggestionList request. If there is no bufferChanged event,
|
||||
// suggestionList will be hidden.
|
||||
if (!textChanged) this.requestHideSuggestionList()
|
||||
}
|
||||
|
||||
// Private: Gets called when the user saves the document. Cancels the
|
||||
// autocompletion.
|
||||
bufferSaved () {
|
||||
if (!this.autosaveEnabled) { return this.hideSuggestionList() }
|
||||
}
|
||||
|
||||
showOrHideSuggestionListForBufferChanges ({changes}) {
|
||||
if (this.disposed) return
|
||||
|
||||
const lastCursorPosition = this.editor.getLastCursor().getBufferPosition()
|
||||
const changeOccurredNearLastCursor = changes.some(({newRange}) => {
|
||||
return newRange.containsPoint(lastCursorPosition)
|
||||
})
|
||||
if (!changeOccurredNearLastCursor) return
|
||||
|
||||
let shouldActivate = false
|
||||
if (this.autoActivationEnabled || this.suggestionList.isActive() && !this.compositionInProgress) {
|
||||
shouldActivate = changes.some(({oldText, newText}) => {
|
||||
if (this.autoActivationEnabled || this.suggestionList.isActive()) {
|
||||
if (newText.length > 0) {
|
||||
// Activate on space, a non-whitespace character, or a bracket-matcher pair.
|
||||
if (newText === ' ' ||
|
||||
newText.trim().length === 1 ||
|
||||
(newText.length === 2 && this.bracketMatcherPairs.includes(newText))) return true
|
||||
} else if (oldText.length > 0 && (this.backspaceTriggersAutocomplete || this.suggestionList.isActive())) {
|
||||
// Suggestion list must be either active or backspaceTriggersAutocomplete must be true for activation to occur.
|
||||
// Activate on removal of a space, a non-whitespace character, or a bracket-matcher pair.
|
||||
if (oldText === ' ' ||
|
||||
oldText.trim().length === 1 ||
|
||||
(oldText.length === 2 && this.bracketMatcherPairs.includes(oldText))) return true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (shouldActivate && this.shouldSuppressActivationForEditorClasses()) shouldActivate = false
|
||||
}
|
||||
|
||||
if (shouldActivate) {
|
||||
this.cancelHideSuggestionListRequest()
|
||||
this.requestNewSuggestions()
|
||||
} else {
|
||||
this.cancelNewSuggestionsRequest()
|
||||
this.hideSuggestionList()
|
||||
}
|
||||
}
|
||||
|
||||
shouldSuppressActivationForEditorClasses () {
|
||||
for (let i = 0; i < this.suppressForClasses.length; i++) {
|
||||
const classNames = this.suppressForClasses[i]
|
||||
let containsCount = 0
|
||||
for (let j = 0; j < classNames.length; j++) {
|
||||
const className = classNames[j]
|
||||
if (this.editorView.classList.contains(className)) { containsCount += 1 }
|
||||
}
|
||||
if (containsCount === classNames.length) { return true }
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Public: Clean up, stop listening to events
|
||||
dispose () {
|
||||
this.hideSuggestionList()
|
||||
this.disposed = true
|
||||
this.ready = false
|
||||
if (this.editorSubscriptions) {
|
||||
this.editorSubscriptions.dispose()
|
||||
}
|
||||
this.editorSubscriptions = null
|
||||
if (this.subscriptions) {
|
||||
this.subscriptions.dispose()
|
||||
}
|
||||
this.subscriptions = null
|
||||
this.suggestionList = null
|
||||
this.providerManager = null
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
const POSSIBLE_WORD_CHARACTERS = '/\\()"\':,.;<>~!@#$%^&*|+=[]{}`?_-…'.split('')
|
||||
|
||||
module.exports =
|
||||
function getAdditionalWordCharacters (scopeDescriptor) {
|
||||
const nonWordCharacters = atom.config.get('editor.nonWordCharacters', {scope: scopeDescriptor})
|
||||
let result = atom.config.get('autocomplete-plus.extraWordCharacters', {scope: scopeDescriptor})
|
||||
POSSIBLE_WORD_CHARACTERS.forEach(character => {
|
||||
if (!nonWordCharacters.includes(character)) {
|
||||
result += character
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
88
packages/autocomplete-plus/lib/main.js
Normal file
88
packages/autocomplete-plus/lib/main.js
Normal file
@ -0,0 +1,88 @@
|
||||
const {CompositeDisposable} = require('atom')
|
||||
const AutocompleteManager = require('./autocomplete-manager')
|
||||
|
||||
module.exports = {
|
||||
subscriptions: null,
|
||||
autocompleteManager: new AutocompleteManager(),
|
||||
|
||||
// Public: Creates AutocompleteManager instances for all active and future editors (soon, just a single AutocompleteManager)
|
||||
activate () {
|
||||
this.subscriptions = new CompositeDisposable()
|
||||
if (!this.autocompleteManager) this.autocompleteManager = new AutocompleteManager()
|
||||
this.subscriptions.add(this.autocompleteManager)
|
||||
this.autocompleteManager.initialize()
|
||||
},
|
||||
|
||||
// Public: Cleans everything up, removes all AutocompleteManager instances
|
||||
deactivate () {
|
||||
if (this.subscriptions) {
|
||||
this.subscriptions.dispose()
|
||||
}
|
||||
this.subscriptions = null
|
||||
this.autocompleteManager = null
|
||||
},
|
||||
|
||||
provideWatchEditor () {
|
||||
return this.autocompleteManager.watchEditor.bind(this.autocompleteManager)
|
||||
},
|
||||
|
||||
consumeSnippets (snippetsManager) {
|
||||
this.autocompleteManager.setSnippetsManager(snippetsManager)
|
||||
},
|
||||
|
||||
/*
|
||||
Section: Provider API
|
||||
*/
|
||||
|
||||
// 1.0.0 API
|
||||
// service - {provider: provider1}
|
||||
consumeProvider_1 (service) {
|
||||
if (!service || !service.provider) {
|
||||
return
|
||||
}
|
||||
return this.consumeProvider([service.provider], 1)
|
||||
},
|
||||
|
||||
// 1.1.0 API
|
||||
// service - {providers: [provider1, provider2, ...]}
|
||||
consumeProvider_1_1 (service) {
|
||||
if (!service || !service.providers) {
|
||||
return
|
||||
}
|
||||
return this.consumeProvider(service.providers, 1)
|
||||
},
|
||||
|
||||
// 2.0.0 API
|
||||
consumeProvider_2 (providers) {
|
||||
return this.consumeProvider(providers, 2)
|
||||
},
|
||||
|
||||
// 3.0.0 API
|
||||
consumeProvider_3 (providers) {
|
||||
return this.consumeProvider(providers, 3)
|
||||
},
|
||||
|
||||
// 4.0.0 API – Simplifies prefix computation
|
||||
consumeProvider_4 (providers) {
|
||||
return this.consumeProvider(providers, 4)
|
||||
},
|
||||
|
||||
consumeProvider (providers, apiVersion = 3) {
|
||||
if (!providers) {
|
||||
return
|
||||
}
|
||||
if (providers && !Array.isArray(providers)) {
|
||||
providers = [providers]
|
||||
}
|
||||
if (!providers.length > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const registrations = new CompositeDisposable()
|
||||
for (let i = 0; i < providers.length; i++) {
|
||||
const provider = providers[i]
|
||||
registrations.add(this.autocompleteManager.providerManager.registerProvider(provider, apiVersion))
|
||||
}
|
||||
return registrations
|
||||
}
|
||||
}
|
4
packages/autocomplete-plus/lib/private-symbols.js
Normal file
4
packages/autocomplete-plus/lib/private-symbols.js
Normal file
@ -0,0 +1,4 @@
|
||||
'use babel'
|
||||
|
||||
const API_VERSION = Symbol('Private property: Semantic version of the service endpoint.')
|
||||
export {API_VERSION}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user