mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-11 19:17:09 +03:00
Merge remote-tracking branch 'origin/master' into bump-electron-13-with-wasm-superstring
This commit is contained in:
commit
69ae6ab3e2
200
.cirrus.yml
200
.cirrus.yml
@ -1,12 +1,16 @@
|
||||
env:
|
||||
PYTHON_VERSION: 3.10
|
||||
|
||||
linux_task:
|
||||
alias: linux
|
||||
container:
|
||||
image: node:lts-slim
|
||||
image: node:16-slim
|
||||
memory: 8G
|
||||
install_deps_script:
|
||||
prepare_script:
|
||||
- apt-get update
|
||||
- export DEBIAN_FRONTEND="noninteractive"
|
||||
- apt-get install -y
|
||||
ffmpeg
|
||||
rpm
|
||||
build-essential
|
||||
git
|
||||
@ -23,7 +27,9 @@ linux_task:
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- sed -i -e "s/[0-9]*-dev/`date -u +%Y%m%d%H`/g" package.json
|
||||
- yarn install || yarn install
|
||||
install_script:
|
||||
- yarn install --ignore-engines || yarn install --ignore-engines
|
||||
build_script:
|
||||
- yarn build
|
||||
- yarn run build:apm
|
||||
build_binary_script:
|
||||
@ -31,6 +37,68 @@ linux_task:
|
||||
binary_artifacts:
|
||||
path: ./binaries/*
|
||||
test_script:
|
||||
- rm -R node_modules/electron; yarn install --check-files
|
||||
- ./binaries/*AppImage --appimage-extract
|
||||
- export BINARY_NAME='squashfs-root/pulsar'
|
||||
- mkdir -p ./tests/videos
|
||||
- Xvfb -screen 0 1024x768x24+32 :99 & nohup ffmpeg -video_size 1024x768 -f x11grab -i :99.0 ./tests/videos/out.mpg & DISPLAY=:99 PLAYWRIGHT_JUNIT_OUTPUT_NAME=report.xml npx playwright test --reporter=junit,list
|
||||
always:
|
||||
videos_artifacts:
|
||||
path: ./tests/videos/**
|
||||
junit_artifacts:
|
||||
path: report.xml
|
||||
type: text/xml
|
||||
format: junit
|
||||
|
||||
arm_linux_task:
|
||||
alias: linux
|
||||
arm_container:
|
||||
image: node:16-slim
|
||||
memory: 8G
|
||||
env:
|
||||
USE_SYSTEM_FPM: 'true'
|
||||
prepare_script:
|
||||
- apt-get update
|
||||
- export DEBIAN_FRONTEND="noninteractive"
|
||||
- apt-get install -y
|
||||
gnupg2
|
||||
procps
|
||||
curl
|
||||
rpm
|
||||
build-essential
|
||||
git
|
||||
libsecret-1-dev
|
||||
fakeroot
|
||||
libx11-dev
|
||||
libxkbfile-dev
|
||||
libgdk-pixbuf2.0-dev
|
||||
libgtk-3-dev
|
||||
libxss-dev
|
||||
libasound2-dev
|
||||
libnss3
|
||||
xvfb
|
||||
- gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
|
||||
- \curl -sSL https://get.rvm.io | bash -s stable
|
||||
- source /etc/profile.d/rvm.sh
|
||||
- rvm install ruby
|
||||
- gem install fpm
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- sed -i -e "s/[0-9]*-dev/`date -u +%Y%m%d%H`/g" package.json
|
||||
install_script:
|
||||
- yarn install --ignore-engines || yarn install --ignore-engines
|
||||
build_script:
|
||||
- yarn build
|
||||
- yarn run build:apm
|
||||
build_binary_script:
|
||||
- source /etc/profile.d/rvm.sh
|
||||
- yarn dist || yarn dist
|
||||
binary_artifacts:
|
||||
path: ./binaries/*
|
||||
test_script:
|
||||
- rm -R node_modules/electron; yarn install --check-files
|
||||
- ./binaries/*AppImage --appimage-extract
|
||||
- export BINARY_NAME='squashfs-root/pulsar'
|
||||
- Xvfb :99 & DISPLAY=:99 PLAYWRIGHT_JUNIT_OUTPUT_NAME=report.xml npx playwright test --reporter=junit,list
|
||||
always:
|
||||
videos_artifacts:
|
||||
@ -40,27 +108,41 @@ linux_task:
|
||||
type: text/xml
|
||||
format: junit
|
||||
|
||||
macos_task:
|
||||
silicon_mac_task:
|
||||
alias: mac
|
||||
macos_instance:
|
||||
image: ghcr.io/cirruslabs/macos-monterey-base:latest
|
||||
image: ghcr.io/cirruslabs/macos-monterey-xcode:14
|
||||
memory: 8G
|
||||
install_deps_script:
|
||||
- sed -i -e "s/[0-9]*-dev/`date -u +%Y%m%d%H`/g" package.json
|
||||
- brew install node@16 yarn git python
|
||||
env:
|
||||
CSC_LINK: ENCRYPTED[0078015a03bb6cfdbd80113ae5bbb6f448fd4bbbc40efd81bf2cb1554373046b475a4d7c77e3e3e82ac1ce2f7e3d2da5]
|
||||
CSC_KEY_PASSWORD: ENCRYPTED[82bb72653d39578035ed1860ab4978703d50bd326d925a146ff08782f987ceb37ac2d8dbace52dec2b0e2ef92debf097]
|
||||
APPLEID: ENCRYPTED[549ce052bd5666dba5245f4180bf93b74ed206fe5e6e7c8f67a8596d3767c1f682b84e347b326ac318c62a07c8844a57]
|
||||
APPLEID_PASSWORD: ENCRYPTED[774c3307fd3b62660ecf5beb8537a24498c76e8d90d7f28e5bc816742fd8954a34ffed13f9aa2d1faf66ce08b4496e6f]
|
||||
TEAM_ID: ENCRYPTED[11f3fedfbaf4aff1859bf6c105f0437ace23d84f5420a2c1cea884fbfa43b115b7834a463516d50cb276d4c4d9128b49]
|
||||
prepare_script:
|
||||
- brew install node@16 yarn git python@$PYTHON_VERSION
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- ln -s /opt/homebrew/bin/python3 /opt/homebrew/bin/python
|
||||
- ln -s /opt/homebrew/bin/python$PYTHON_VERSION /opt/homebrew/bin/python
|
||||
- export PATH="/opt/homebrew/bin:/opt/homebrew/opt/node@16/bin:$PATH"
|
||||
- sed -i -e "s/[0-9]*-dev/`date -u +%Y%m%d%H`/g" package.json
|
||||
install_script:
|
||||
- export PATH="/opt/homebrew/bin:/opt/homebrew/opt/node@16/bin:$PATH"
|
||||
- yarn install --ignore-engines || yarn install --ignore-engines
|
||||
build_script:
|
||||
- export PATH="/opt/homebrew/bin:/opt/homebrew/opt/node@16/bin:$PATH"
|
||||
- yarn install || yarn install
|
||||
- yarn build
|
||||
- yarn run build:apm
|
||||
build_arm_binary_script:
|
||||
build_binary_script:
|
||||
- export PATH="/opt/homebrew/bin:/opt/homebrew/opt/node@16/bin:$PATH"
|
||||
- yarn dist || yarn dist
|
||||
arm_binary_artifacts:
|
||||
binary_artifacts:
|
||||
path: ./binaries/*
|
||||
test_script:
|
||||
- export PATH="/opt/homebrew/bin:/opt/homebrew/opt/node@16/bin:$PATH"
|
||||
- rm -R node_modules/electron; yarn install --check-files
|
||||
- hdiutil mount binaries/Pulsar*dmg
|
||||
- export BINARY_NAME=`ls /Volumes/Pulsar*/Pulsar.app/Contents/MacOS/Pulsar`
|
||||
- PLAYWRIGHT_JUNIT_OUTPUT_NAME=report.xml npx playwright test --reporter=junit,list
|
||||
always:
|
||||
videos_artifacts:
|
||||
@ -69,52 +151,90 @@ macos_task:
|
||||
path: report.xml
|
||||
type: text/xml
|
||||
format: junit
|
||||
build_x86_dependencies_script:
|
||||
- echo A | softwareupdate --install-rosetta
|
||||
- arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
|
||||
- export PATH="/usr/local/bin:$PATH"
|
||||
- arch -x86_64 brew install node@16 yarn git python
|
||||
- export PATH="/usr/local/opt/node@16/bin:/usr/local/bin/python3:$PATH"
|
||||
- yarn install || yarn install
|
||||
- ln -s /usr/local/opt/python3 /usr/local/bin/python
|
||||
- arch -x86_64 npx yarn install || arch -x86_64 npx yarn install
|
||||
- arch -x86_64 npx yarn build
|
||||
- arch -x86_64 npx yarn run build:apm
|
||||
dist_x86_binary_script:
|
||||
- export PATH="/opt/homebrew/bin:/opt/homebrew/opt/node@16/bin:$PATH"
|
||||
|
||||
intel_mac_task:
|
||||
alias: mac
|
||||
macos_instance:
|
||||
image: ghcr.io/cirruslabs/macos-monterey-xcode:14
|
||||
memory: 8G
|
||||
env:
|
||||
CSC_LINK: ENCRYPTED[0078015a03bb6cfdbd80113ae5bbb6f448fd4bbbc40efd81bf2cb1554373046b475a4d7c77e3e3e82ac1ce2f7e3d2da5]
|
||||
CSC_KEY_PASSWORD: ENCRYPTED[82bb72653d39578035ed1860ab4978703d50bd326d925a146ff08782f987ceb37ac2d8dbace52dec2b0e2ef92debf097]
|
||||
APPLEID: ENCRYPTED[549ce052bd5666dba5245f4180bf93b74ed206fe5e6e7c8f67a8596d3767c1f682b84e347b326ac318c62a07c8844a57]
|
||||
APPLEID_PASSWORD: ENCRYPTED[774c3307fd3b62660ecf5beb8537a24498c76e8d90d7f28e5bc816742fd8954a34ffed13f9aa2d1faf66ce08b4496e6f]
|
||||
TEAM_ID: ENCRYPTED[11f3fedfbaf4aff1859bf6c105f0437ace23d84f5420a2c1cea884fbfa43b115b7834a463516d50cb276d4c4d9128b49]
|
||||
prepare_script:
|
||||
- sudo rm -rf /Library/Developer/CommandLineTools
|
||||
- echo A | softwareupdate --install-rosetta
|
||||
- arch -x86_64 xcode-select --install
|
||||
- arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
|
||||
- export PATH="/usr/local/opt/node@16/bin:/usr/local/bin:$PATH"
|
||||
- arch -x86_64 brew install node@16 yarn git python@$PYTHON_VERSION
|
||||
- ln -s /usr/local/bin/python$PYTHON_VERSION /usr/local/bin/python
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- sed -i -e "s/[0-9]*-dev/`date -u +%Y%m%d%H`/g" package.json
|
||||
install_script:
|
||||
- export PATH="/usr/local/opt/node@16/bin:/usr/local/bin:$PATH"
|
||||
- arch -x86_64 npx yarn install --ignore-engines || arch -x86_64 npx yarn install --ignore-engines
|
||||
build_script:
|
||||
- export PATH="/usr/local/opt/node@16/bin:/usr/local/bin:$PATH"
|
||||
- arch -x86_64 npx yarn build
|
||||
- arch -x86_64 yarn run build:apm
|
||||
build_binary_script:
|
||||
- export PATH="/usr/local/opt/node@16/bin:/usr/local/bin:$PATH"
|
||||
- arch -x86_64 npx yarn dist || arch -x86_64 npx yarn dist
|
||||
x86_binary_artifacts:
|
||||
binary_artifacts:
|
||||
path: ./binaries/*
|
||||
test_script:
|
||||
- export PATH="/usr/local/opt/node@16/bin:/usr/local/bin:$PATH"
|
||||
- rm -R node_modules/electron; yarn install --check-files
|
||||
- hdiutil mount binaries/Pulsar*dmg
|
||||
- export BINARY_NAME=`ls /Volumes/Pulsar*/Pulsar.app/Contents/MacOS/Pulsar`
|
||||
- PLAYWRIGHT_JUNIT_OUTPUT_NAME=report.xml arch -x86_64 npx playwright test --reporter=junit,list
|
||||
always:
|
||||
videos_artifacts:
|
||||
path: ./tests/videos/**
|
||||
junit_artifacts:
|
||||
path: report.xml
|
||||
type: text/xml
|
||||
format: junit
|
||||
|
||||
windows_task:
|
||||
alias: windows
|
||||
timeout_in: 90m
|
||||
windows_container:
|
||||
image: cirrusci/windowsservercore:visualstudio2022-2022.06.23
|
||||
env:
|
||||
CIRRUS_SHELL: bash
|
||||
PATH: C:\Python310\Scripts\;C:\Python310\;%PATH%;C:\Program Files\nodejs\;C:\Program Files\Git\cmd;C:\Users\User\AppData\Local\Microsoft\WindowsApps;C:\Users\User\AppData\Roaming\npm;C:\Program Files\Microsoft Visual Studio\2022\Community\Msbuild\Current\Bin\
|
||||
install_deps_script:
|
||||
- choco install nodejs --version=14.15.0 -y
|
||||
- choco install python git visualstudio2019-workload-vctools -y
|
||||
prepare_script:
|
||||
- choco install nodejs --version=16.16.0 -y
|
||||
- choco install python --version=3.10.3 -y
|
||||
- choco install git visualstudio2019-workload-vctools -y
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- npm config set python 'C:\Python310\python.exe'
|
||||
build_apm_script:
|
||||
- cd ppm; npx yarn install --ignore-engines || npx yarn install --ignore-engines || npx yarn cache clean; npx yarn install --ignore-engines || npx yarn install --ignore-engines
|
||||
install_without_scripts_script:
|
||||
- npx yarn install --ignore-scripts --ignore-engines || sleep 1 && npx yarn install --ignore-engines --ignore-scripts || sleep 2 && npx yarn cache clean; npx yarn install --ignore-engines --ignore-scripts || sleep 2 && npx yarn install --ignore-engines --ignore-scripts || echo "Giving up"
|
||||
rebuild_for_electron_script:
|
||||
install_script:
|
||||
- npx yarn install --ignore-engines
|
||||
|| rm -R node_modules && npx yarn install --ignore-engines
|
||||
|| rm -R node_modules && npx yarn install --ignore-engines
|
||||
build_script:
|
||||
- npx yarn build:apm
|
||||
- npx yarn build || npx yarn build || npx yarn build
|
||||
# install_only_electron_script:
|
||||
# - rm -R node_modules/electron
|
||||
# - npx yarn install --ignore-engines || npx yarn install --ignore-engines || npx yarn cache clean; npx yarn install --ignore-engines || npx yarn install --ignore-engines
|
||||
# - npx playwright test --reporter=list
|
||||
videos_artifacts:
|
||||
path: tests\videos\**
|
||||
build_binary_script:
|
||||
- sed -i -e "s/[0-9]*-dev/`date -u +%Y%m%d%H`/g" package.json
|
||||
- npx yarn dist || npx yarn dist || npx yarn dist
|
||||
binary_artifacts:
|
||||
path: .\binaries\*
|
||||
test_script:
|
||||
- mkdir extracted; tar -xf binaries/*zip -C ./extracted/
|
||||
- export BINARY_NAME=./extracted/Pulsar.exe
|
||||
- PLAYWRIGHT_JUNIT_OUTPUT_NAME=report.xml npx playwright test --reporter=junit,list || echo "Yeah, tests failed, Windows is like this"
|
||||
always:
|
||||
videos_artifacts:
|
||||
path: ./tests/videos/**
|
||||
junit_artifacts:
|
||||
path: report.xml
|
||||
type: text/xml
|
||||
format: junit
|
||||
|
33
.codacy.yaml
Normal file
33
.codacy.yaml
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
engines:
|
||||
duplication:
|
||||
minTokenMatch: 80
|
||||
exclude_paths:
|
||||
- "spec/fixtures/**"
|
||||
- "packages/*/spec/fixtures/**"
|
||||
|
||||
# Since Codacy exposes significantly little on the config.
|
||||
# We can use the rest of this document to solidify our settings.
|
||||
#
|
||||
# Quality Settings: (Below are changed values, rest are default)
|
||||
# * Pull requests won't pass the quality gate when:
|
||||
# - New issues are over: 15 'critical'
|
||||
# * Commits won't pass the quality gate:
|
||||
# - New issues are over: 15 'critical'
|
||||
# * The repository is below the quality goals when:
|
||||
# - Issues are over: 20%
|
||||
# - Complexity is over: 10%
|
||||
# - File is complex when over: 20
|
||||
# - Duplication is over: 30
|
||||
# - File is duplicated when over: 1 'cloned block'
|
||||
# - Coverage is under: 60%
|
||||
# Enabled Engines:
|
||||
# - CSSLint 1.0.5
|
||||
# - CoffeeLint 2.1.0
|
||||
# - ESLint 8.23.1
|
||||
# - Hadolint 1.18.2
|
||||
# - Jackson Linter 2.10.2
|
||||
# - PMD 6.48.0
|
||||
# - SpellCheck 0.8.0
|
||||
# - Stylelint 14.2.0
|
||||
#
|
@ -1,4 +0,0 @@
|
||||
**/spec/fixtures/**/*.js
|
||||
node_modules
|
||||
/vendor/
|
||||
/out/
|
30
.eslintrc.js
Normal file
30
.eslintrc.js
Normal file
@ -0,0 +1,30 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
commonjs: true,
|
||||
es2021: true,
|
||||
},
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:node/recommended",
|
||||
"plugin:jsdoc/recommended"
|
||||
],
|
||||
overrides: [],
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest"
|
||||
},
|
||||
rules: {
|
||||
"node/no-unpublished-require": [
|
||||
"error",
|
||||
{
|
||||
allowModules: ["electron"]
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
"jsdoc"
|
||||
],
|
||||
globals: {
|
||||
atom: "writeable"
|
||||
}
|
||||
};
|
@ -1,44 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"./script/node_modules/eslint-config-standard/eslintrc.json",
|
||||
"./script/node_modules/eslint-config-prettier/index.js",
|
||||
"./script/node_modules/eslint-config-prettier/standard.js"
|
||||
],
|
||||
"plugins": [
|
||||
"prettier"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 8,
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"globals": {
|
||||
"atom": true,
|
||||
"snapshotResult": true
|
||||
},
|
||||
"rules": {
|
||||
"standard/no-callback-literal": ["off"],
|
||||
"node/no-deprecated-api": ["off"],
|
||||
"prettier/prettier": ["error"]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["spec/**", "**-spec.js", "**.test.js"],
|
||||
"env": {
|
||||
"jasmine": true
|
||||
},
|
||||
"globals": {
|
||||
"advanceClock": true,
|
||||
"fakeClearInterval": true,
|
||||
"fakeSetInterval": true,
|
||||
"waitsForPromise": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
10
.gitattributes
vendored
10
.gitattributes
vendored
@ -15,13 +15,3 @@ spec/fixtures/sample.txt text eol=lf
|
||||
|
||||
# Windows bash scripts are also Unix LF endings
|
||||
*.sh eol=lf
|
||||
|
||||
# The script executables should be LF so they can be edited on Windows
|
||||
script/bootstrap text eol=lf
|
||||
script/build text eol=lf
|
||||
script/cibuild text eol=lf
|
||||
script/clean text eol=lf
|
||||
script/lint text eol=lf
|
||||
script/postprocess-junit-results text eol=lf
|
||||
script/test text eol=lf
|
||||
script/verify-snapshot-script text eol=lf
|
||||
|
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
|
13
.github/workflows/editor-tests.yml
vendored
13
.github/workflows/editor-tests.yml
vendored
@ -1,13 +1,20 @@
|
||||
name: Editor tests
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ATOM_JASMINE_REPORTER: list
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: tests
|
||||
if: |
|
||||
!startsWith(github.event.pull_request.title, '[skip-ci]') &&
|
||||
!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:
|
||||
@ -28,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
|
||||
|
183
.github/workflows/package-tests-linux.yml
vendored
183
.github/workflows/package-tests-linux.yml
vendored
@ -1,20 +1,17 @@
|
||||
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: setup
|
||||
name: Build Editor
|
||||
if: |
|
||||
!startsWith(github.event.pull_request.title, '[skip-ci]') &&
|
||||
!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
|
||||
|
||||
@ -23,69 +20,153 @@ jobs:
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: install dependencies
|
||||
- name: Install Dependencies
|
||||
run: yarn install
|
||||
|
||||
- name: build dependencies
|
||||
- name: Build Dependencies
|
||||
run: yarn build
|
||||
|
||||
- name: build dependencies
|
||||
run: yarn build:apm
|
||||
|
||||
- name: cache node module
|
||||
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 module
|
||||
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: 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
|
||||
fail-fast: false
|
||||
- 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"
|
||||
|
||||
name: test ${{ matrix.descr }} packages
|
||||
runs-on: ubuntu-20.04
|
||||
needs: setup
|
||||
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 module
|
||||
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: cache APM module
|
||||
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 ${{ matrix.descr }} packages' tests
|
||||
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 }}/)"
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -18,4 +18,6 @@ docs/includes
|
||||
spec/fixtures/evil-files/
|
||||
!spec/fixtures/packages/package-with-incompatible-native-module-loaded-conditionally/node_modules/
|
||||
out/
|
||||
dist/
|
||||
binaries/
|
||||
/electron/
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"singleQuote": true
|
||||
}
|
352
CHANGELOG.md
352
CHANGELOG.md
@ -1 +1,351 @@
|
||||
See https://atom.io/releases
|
||||
# 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]
|
||||
|
||||
- The settings-view package now lists a package’s snippets more accurately
|
||||
- Fixed some issues with some packages with WebComponents v0 (tablr package
|
||||
should work now) by internalizing and patching document-register-element
|
||||
- Migrated away from `node-oniguruma` in favor of `vscode-oniguruma` (WASM
|
||||
version). This fixes issues with Electron 21
|
||||
|
||||
## 1.103.0
|
||||
|
||||
- Added a new feature to Search for Pulsar's settings
|
||||
- Updated the completions provided by `autocomplete-css` to be as bleeding edge as possible.
|
||||
- Updated the instructions and look of the login flow for the `github` package.
|
||||
- Snippet transformations no longer have an implied global flag, bringing them into compatibility with snippets in most other editors.
|
||||
- Snippets can now be given command names instead of tab triggers, and thus can now be assigned to key shortcuts in `keymap.cson`.
|
||||
|
||||
### Pulsar
|
||||
- Added: feature: Implement Search Settings Ability [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/416)
|
||||
- Added: Show Settings Icon in Status Bar [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/421)
|
||||
- Added: Add Automated updated of `autocomplete-css` `completions.json` [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/398)
|
||||
- Bumped: ppm: Update submodule to 9af239277180f2a9ee9e86714 [@Spiker985](https://github.com/pulsar-edit/pulsar/pull/403)
|
||||
- Bumped: ppm: Update submodule to 915cbf6e5f9ea1141ef5dcaf8 [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/418)
|
||||
- Bumped: deps: Bump github to v0.36.15-pretranspiled [@DeeDeeG](https://github.com/pulsar-edit/pulsar/pull/415)
|
||||
- Added: actually cache based on sha [@Meadowsys](https://github.com/pulsar-edit/pulsar/pull/412)
|
||||
- Bumped: Bump `snippets` to bb00f9 [@savetheclocktower](https://github.com/pulsar-edit/pulsar/pull/408)
|
||||
- Added: [skip-ci] Small Readme Touchup [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/404)
|
||||
- Added: json language - add .har extension [@wesinator](https://github.com/pulsar-edit/pulsar/pull/396)
|
||||
- Added: Bundle `markdown-preview`, `styleguide`, `wrap-guide` [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/374)
|
||||
- Added: Add GitHub Token to Doc CI [@Spiker985](https://github.com/pulsar-edit/pulsar/pull/400)
|
||||
- Added: Add Setup Node to Package Tests [@confused-Techie](https://github.com/pulsar-edit/pulsar/pull/399)
|
||||
- Added: feat: add dev.pulsar_edit.Pulsar.metainfo.xml [@cat-master21](https://github.com/pulsar-edit/pulsar/pull/380)
|
||||
|
||||
### Snippets
|
||||
- Added: Add `command` property that registers a command name for a snippet [@savetheclocktower](https://github.com/pulsar-edit/snippets/pull/10)
|
||||
- Removed: Remove implicit `g` flag from snippet transformations [@savetheclocktower](https://github.com/pulsar-edit/snippets/pull/7)
|
||||
- Fixed: Fix failing specs [@mauricioszabo](https://github.com/pulsar-edit/snippets/pull/6)
|
||||
- Added: cleanup and rename [@Sertonix](https://github.com/pulsar-edit/snippets/pull/5)
|
||||
|
||||
### Github
|
||||
- Added: rebrand git-tab-view [@icecream17](https://github.com/pulsar-edit/github/pull/17)
|
||||
- Added: lib: Update login instructions for PATs, not OAuth [@DeeDeeG](https://github.com/pulsar-edit/github/pull/15)
|
||||
|
||||
### PPM
|
||||
- Fixed: src: Update default Pulsar install paths [@DeeDeeG](https://github.com/pulsar-edit/ppm/pull/49)
|
||||
- Bumped: deps: Upgrade npm to 6.14.18 [@DeeDeeG](https://github.com/pulsar-edit/ppm/pull/53)
|
||||
- Fixed: Fix installing with yarn on Windows [@DeeDeeG](https://github.com/pulsar-edit/ppm/pull/58)
|
||||
- Fixed: Fix inability to notice newer versions of git-installed packages [@savetheclocktower](https://github.com/pulsar-edit/ppm/pull/59)
|
||||
- Added: meta: Actually sync yarn.lock [@DeeDeeG](https://github.com/pulsar-edit/ppm/pull/60)
|
||||
|
||||
## 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 infrastructure 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 rebranding API
|
||||
- Removed experimental file watchers on the editor
|
||||
- Ability to install packages from git repositories
|
||||
- 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 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
|
||||
|
||||
### 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
|
||||
|
@ -145,7 +145,7 @@ Include details about your configuration and environment:
|
||||
* **What's the name and version of the OS you're using**?
|
||||
* **Are you running Atom in a virtual machine?** If so, which VM software are you using and which operating systems and versions are used for the host and the guest?
|
||||
* **Which [packages](#atom-and-packages) do you have installed?** You can get that list by running `apm list --installed`.
|
||||
* **Are you using [local configuration files](https://flight-manual.atom.io/using-atom/sections/basic-customization/)** `config.cson`, `keymap.cson`, `snippets.cson`, `styles.less` and `init.coffee` to customize Atom? If so, provide the contents of those files, preferably in a [code block](https://help.github.com/articles/markdown-basics/#multiple-lines) or with a link to a [gist](https://gist.github.com/).
|
||||
* **Are you using [local configuration files](https://flight-manual.atom.io/using-atom/sections/basic-customization/)** `config.cson`, `keymap.cson`, `snippets.cson`, `styles.less` and `init.js` to customize Atom? If so, provide the contents of those files, preferably in a [code block](https://help.github.com/articles/markdown-basics/#multiple-lines) or with a link to a [gist](https://gist.github.com/).
|
||||
* **Are you using Atom with multiple monitors?** If so, can you reproduce the problem when you use a single monitor?
|
||||
* **Which keyboard layout are you using?** Are you using a US layout or some other layout?
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
# VERSION: 0.2
|
||||
# DESCRIPTION: Image to build Atom
|
||||
# DESCRIPTION: Image to build Pulsar
|
||||
|
||||
FROM ubuntu:20.04
|
||||
|
||||
|
36
LICENSE.md
36
LICENSE.md
@ -1,20 +1,22 @@
|
||||
Copyright (c) 2011-2022 GitHub Inc.
|
||||
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-2023 Pulsar-Edit
|
||||
Original work copyright (c) 2011-2022 GitHub Inc.
|
||||
|
||||
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.
|
||||
|
67
README.md
67
README.md
@ -1,69 +1,85 @@
|
||||
|
||||
<br>
|
||||
|
||||
<div align = center>
|
||||
|
||||
<!-- ![Banner] -->
|
||||
<br>
|
||||
[![Badge Discussions]][Discussions]
|
||||
[![Badge Discord]][Discord]
|
||||
[![Badge Reddit]][Reddit]
|
||||
|
||||
[![Badge Status]][Status]
|
||||
[![Badge License]][License]
|
||||
|
||||
<br>
|
||||
|
||||
# Pulsar
|
||||
|
||||
<br>
|
||||
|
||||
[![Button Install]][Install]
|
||||
[![Button Documentation]][Documentation]
|
||||
[![Button Build]][Build]
|
||||
|
||||
[![Badge License]][License]
|
||||
[![Badge Guidelines]][Guidelines]
|
||||
[![Badge Status]][Status]
|
||||
[![Badge Sunset]][Retired]
|
||||
[![Badge Discord]][Discord]
|
||||
[![Badge Codacy]][Codacy]
|
||||
[![Badge Crowdin]][Crowdin]
|
||||
[![Badge OpenCollective]][OpenCollective]
|
||||
|
||||
<br>
|
||||
|
||||
*A hackable text editor for the 21st century, built on **[Electron]**,* <br>
|
||||
*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* <br>
|
||||
*Designed to be deeply customizable, but still*
|
||||
*approachable using the default configuration.*
|
||||
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
![Preview]
|
||||
[![Preview]][#]
|
||||
|
||||
</div>
|
||||
|
||||
<!---------------------------{ Links }--------------------------->
|
||||
|
||||
[Guidelines]: https://github.com/logos 'Branding Guidelines'
|
||||
[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
|
||||
[Codacy]: https://app.codacy.com/gh/pulsar-edit/pulsar
|
||||
[Reddit]: https://www.reddit.com/r/pulsaredit/
|
||||
|
||||
[#]: #
|
||||
|
||||
<!---------------------------{ Files }--------------------------->
|
||||
|
||||
[Documentation]: docs/Documentation.md 'Information how to use & work with Pulsar.'
|
||||
[Install]: docs/Installation.md 'How to install Pulsar on your system.'
|
||||
[Retired]: docs/Retirement.md 'Check out what happened to the original Atom project.'
|
||||
<!---------------------------{ Documents }--------------------------->
|
||||
|
||||
[Documentation]: https://pulsar-edit.dev/docs/ 'Information how to use & work with Pulsar.'
|
||||
[Install]: https://pulsar-edit.dev/docs/launch-manual/sections/getting-started/#installing-pulsar 'How to install Pulsar on your system.'
|
||||
[Build]: https://pulsar-edit.dev/docs/launch-manual/sections/core-hacking/#building-pulsar 'Instructions on how to build Pulsar by yourself.'
|
||||
|
||||
[License]: LICENSE.md
|
||||
[Build]: docs/Building.md 'Instructions on how to build Pulsar by yourself.'
|
||||
|
||||
|
||||
<!---------------------------{ Images }--------------------------->
|
||||
|
||||
[Preview]: https://user-images.githubusercontent.com/378023/49132478-f4b77680-f31f-11e8-9e10-e8454d8d9b7e.png 'Preview of the editor.'
|
||||
[Banner]: https://user-images.githubusercontent.com/378023/49132477-f4b77680-f31f-11e8-8357-ac6491761c6c.png
|
||||
[Preview]: resources/readme.png 'Preview of the editor.'
|
||||
|
||||
|
||||
<!---------------------------{ Badges }--------------------------->
|
||||
|
||||
[Badge Guidelines]: https://img.shields.io/badge/Logo-Guidelines-d36e2d.svg?style=for-the-badge&labelColor=323232
|
||||
[Badge Retired]: https://img.shields.io/badge/Retired-bb3c1f.svg?style=for-the-badge&labelColor=323232&label=Upstream%20Status
|
||||
[Badge Sunset]: https://img.shields.io/badge/Sunset-orange.svg?style=for-the-badge&labelColor=323232&label=Upstream%20Status
|
||||
[Badge Discord]: https://img.shields.io/badge/Discord-6399c4.svg?style=for-the-badge&labelColor=323232&logoColor=white&logo=Discord
|
||||
[Badge License]: https://img.shields.io/badge/License-MIT-e5ab42.svg?style=for-the-badge&labelColor=323232
|
||||
[Badge Status]: https://img.shields.io/cirrus/github/pulsar-edit/pulsar?style=for-the-badge&labelColor=323232&label=Build%20Status
|
||||
[Badge OpenCollective]: https://opencollective.com/pulsar-edit/tiers/badge.svg
|
||||
[Badge Discussions]: https://img.shields.io/github/discussions/pulsar-edit/.github?style=for-the-badge&labelColor=78af9f&color=5a8377
|
||||
[Badge Upstream]: https://img.shields.io/badge/Upstream_Status-Sunset-966227.svg?style=for-the-badge&labelColor=c38033
|
||||
[Badge Discord]: https://img.shields.io/badge/Discord-4b7494.svg?style=for-the-badge&labelColor=6399c4&logoColor=white&logo=Discord
|
||||
[Badge License]: https://img.shields.io/badge/License-MIT-ac7f31.svg?style=for-the-badge&labelColor=e5ab42
|
||||
[Badge Crowdin]: https://badges.crowdin.net/pulsar-edit/localized.svg
|
||||
[Badge Codacy]: https://app.codacy.com/project/badge/Grade/24873ecb93dc4c1d865202ce5b24efc1
|
||||
[Badge Reddit]: https://img.shields.io/reddit/subreddit-subscribers/pulsaredit?style=for-the-badge&label=Reddit&logoColor=white&logo=Reddit&labelColor=e05d44&color=b14835
|
||||
[Badge Status]: https://img.shields.io/cirrus/github/pulsar-edit/pulsar?style=for-the-badge&labelColor=c77b7f&label=Build%20Status&color=8d575a
|
||||
|
||||
|
||||
<!--------------------------{ Buttons }--------------------------->
|
||||
@ -71,4 +87,3 @@
|
||||
[Button Documentation]: https://img.shields.io/badge/Documentation-6399c4?style=for-the-badge&logoColor=white&logo=GitBook
|
||||
[Button Install]: https://img.shields.io/badge/Install-78af9f?style=for-the-badge&logoColor=white&logo=DocuSign
|
||||
[Button Build]: https://img.shields.io/badge/Building-e5ab42?style=for-the-badge&logoColor=white&logo=GNUBash
|
||||
|
||||
|
@ -1,75 +0,0 @@
|
||||
const Chart = require('chart.js');
|
||||
const glob = require('glob');
|
||||
const fs = require('fs-plus');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = async ({ test, benchmarkPaths }) => {
|
||||
document.body.style.backgroundColor = '#ffffff';
|
||||
document.body.style.overflow = 'auto';
|
||||
|
||||
let paths = [];
|
||||
for (const benchmarkPath of benchmarkPaths) {
|
||||
if (fs.isDirectorySync(benchmarkPath)) {
|
||||
paths = paths.concat(
|
||||
glob.sync(path.join(benchmarkPath, '**', '*.bench.js'))
|
||||
);
|
||||
} else {
|
||||
paths.push(benchmarkPath);
|
||||
}
|
||||
}
|
||||
|
||||
while (paths.length > 0) {
|
||||
const benchmark = require(paths.shift())({ test });
|
||||
let results;
|
||||
if (benchmark instanceof Promise) {
|
||||
results = await benchmark;
|
||||
} else {
|
||||
results = benchmark;
|
||||
}
|
||||
|
||||
const dataByBenchmarkName = {};
|
||||
for (const { name, duration, x } of results) {
|
||||
dataByBenchmarkName[name] = dataByBenchmarkName[name] || { points: [] };
|
||||
dataByBenchmarkName[name].points.push({ x, y: duration });
|
||||
}
|
||||
|
||||
const benchmarkContainer = document.createElement('div');
|
||||
document.body.appendChild(benchmarkContainer);
|
||||
for (const key in dataByBenchmarkName) {
|
||||
const data = dataByBenchmarkName[key];
|
||||
if (data.points.length > 1) {
|
||||
const canvas = document.createElement('canvas');
|
||||
benchmarkContainer.appendChild(canvas);
|
||||
// eslint-disable-next-line no-new
|
||||
new Chart(canvas, {
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{ label: key, fill: false, data: data.points }]
|
||||
},
|
||||
options: {
|
||||
showLines: false,
|
||||
scales: { xAxes: [{ type: 'linear', position: 'bottom' }] }
|
||||
}
|
||||
});
|
||||
|
||||
const textualOutput =
|
||||
`${key}:\n\n` + data.points.map(p => `${p.x}\t${p.y}`).join('\n');
|
||||
console.log(textualOutput);
|
||||
} else {
|
||||
const title = document.createElement('h2');
|
||||
title.textContent = key;
|
||||
benchmarkContainer.appendChild(title);
|
||||
const duration = document.createElement('p');
|
||||
duration.textContent = `${data.points[0].y}ms`;
|
||||
benchmarkContainer.appendChild(duration);
|
||||
|
||||
const textualOutput = `${key}: ${data.points[0].y}`;
|
||||
console.log(textualOutput);
|
||||
}
|
||||
|
||||
await global.atom.reset();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
@ -1,100 +0,0 @@
|
||||
const { TextEditor, TextBuffer } = require('atom');
|
||||
|
||||
const MIN_SIZE_IN_KB = 0 * 1024;
|
||||
const MAX_SIZE_IN_KB = 10 * 1024;
|
||||
const SIZE_STEP_IN_KB = 1024;
|
||||
const LINE_TEXT = 'Lorem ipsum dolor sit amet\n';
|
||||
const TEXT = LINE_TEXT.repeat(
|
||||
Math.ceil((MAX_SIZE_IN_KB * 1024) / LINE_TEXT.length)
|
||||
);
|
||||
|
||||
module.exports = async ({ test }) => {
|
||||
const data = [];
|
||||
|
||||
document.body.appendChild(atom.workspace.getElement());
|
||||
|
||||
atom.packages.loadPackages();
|
||||
await atom.packages.activate();
|
||||
|
||||
for (let pane of atom.workspace.getPanes()) {
|
||||
pane.destroy();
|
||||
}
|
||||
|
||||
for (
|
||||
let sizeInKB = MIN_SIZE_IN_KB;
|
||||
sizeInKB < MAX_SIZE_IN_KB;
|
||||
sizeInKB += SIZE_STEP_IN_KB
|
||||
) {
|
||||
const text = TEXT.slice(0, sizeInKB * 1024);
|
||||
console.log(text.length / 1024);
|
||||
|
||||
let t0 = window.performance.now();
|
||||
const buffer = new TextBuffer({ text });
|
||||
const editor = new TextEditor({
|
||||
buffer,
|
||||
autoHeight: false,
|
||||
largeFileMode: true
|
||||
});
|
||||
atom.grammars.autoAssignLanguageMode(buffer);
|
||||
atom.workspace.getActivePane().activateItem(editor);
|
||||
let t1 = window.performance.now();
|
||||
|
||||
data.push({
|
||||
name: 'Opening a large file',
|
||||
x: sizeInKB,
|
||||
duration: t1 - t0
|
||||
});
|
||||
|
||||
const tickDurations = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await timeout(50);
|
||||
t0 = window.performance.now();
|
||||
await timeout(0);
|
||||
t1 = window.performance.now();
|
||||
tickDurations[i] = t1 - t0;
|
||||
}
|
||||
|
||||
data.push({
|
||||
name: 'Max time event loop was blocked after opening a large file',
|
||||
x: sizeInKB,
|
||||
duration: Math.max(...tickDurations)
|
||||
});
|
||||
|
||||
t0 = window.performance.now();
|
||||
editor.setCursorScreenPosition(
|
||||
editor.element.screenPositionForPixelPosition({
|
||||
top: 100,
|
||||
left: 30
|
||||
})
|
||||
);
|
||||
t1 = window.performance.now();
|
||||
|
||||
data.push({
|
||||
name: 'Clicking the editor after opening a large file',
|
||||
x: sizeInKB,
|
||||
duration: t1 - t0
|
||||
});
|
||||
|
||||
t0 = window.performance.now();
|
||||
editor.element.setScrollTop(editor.element.getScrollTop() + 100);
|
||||
t1 = window.performance.now();
|
||||
|
||||
data.push({
|
||||
name: 'Scrolling down after opening a large file',
|
||||
x: sizeInKB,
|
||||
duration: t1 - t0
|
||||
});
|
||||
|
||||
editor.destroy();
|
||||
buffer.destroy();
|
||||
await timeout(10000);
|
||||
}
|
||||
|
||||
atom.workspace.getElement().remove();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
function timeout(duration) {
|
||||
return new Promise(resolve => setTimeout(resolve, duration));
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { TextEditor, TextBuffer } = require('atom');
|
||||
|
||||
const SIZES_IN_KB = [512, 1024, 2048];
|
||||
const REPEATED_TEXT = fs
|
||||
.readFileSync(
|
||||
path.join(__dirname, '..', 'spec', 'fixtures', 'sample.js'),
|
||||
'utf8'
|
||||
)
|
||||
.replace(/\n/g, '');
|
||||
const TEXT = REPEATED_TEXT.repeat(
|
||||
Math.ceil((SIZES_IN_KB[SIZES_IN_KB.length - 1] * 1024) / REPEATED_TEXT.length)
|
||||
);
|
||||
|
||||
module.exports = async ({ test }) => {
|
||||
const data = [];
|
||||
|
||||
const workspaceElement = atom.workspace.getElement();
|
||||
document.body.appendChild(workspaceElement);
|
||||
|
||||
atom.packages.loadPackages();
|
||||
await atom.packages.activate();
|
||||
|
||||
console.log(atom.getLoadSettings().resourcePath);
|
||||
|
||||
for (let pane of atom.workspace.getPanes()) {
|
||||
pane.destroy();
|
||||
}
|
||||
|
||||
for (const sizeInKB of SIZES_IN_KB) {
|
||||
const text = TEXT.slice(0, sizeInKB * 1024);
|
||||
console.log(text.length / 1024);
|
||||
|
||||
let t0 = window.performance.now();
|
||||
const buffer = new TextBuffer({ text });
|
||||
const editor = new TextEditor({
|
||||
buffer,
|
||||
autoHeight: false,
|
||||
largeFileMode: true
|
||||
});
|
||||
atom.grammars.assignLanguageMode(buffer, 'source.js');
|
||||
atom.workspace.getActivePane().activateItem(editor);
|
||||
let t1 = window.performance.now();
|
||||
|
||||
data.push({
|
||||
name: 'Opening a large single-line file',
|
||||
x: sizeInKB,
|
||||
duration: t1 - t0
|
||||
});
|
||||
|
||||
const tickDurations = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await timeout(50);
|
||||
t0 = window.performance.now();
|
||||
await timeout(0);
|
||||
t1 = window.performance.now();
|
||||
tickDurations[i] = t1 - t0;
|
||||
}
|
||||
|
||||
data.push({
|
||||
name:
|
||||
'Max time event loop was blocked after opening a large single-line file',
|
||||
x: sizeInKB,
|
||||
duration: Math.max(...tickDurations)
|
||||
});
|
||||
|
||||
t0 = window.performance.now();
|
||||
editor.setCursorScreenPosition(
|
||||
editor.element.screenPositionForPixelPosition({
|
||||
top: 100,
|
||||
left: 30
|
||||
})
|
||||
);
|
||||
t1 = window.performance.now();
|
||||
|
||||
data.push({
|
||||
name: 'Clicking the editor after opening a large single-line file',
|
||||
x: sizeInKB,
|
||||
duration: t1 - t0
|
||||
});
|
||||
|
||||
t0 = window.performance.now();
|
||||
editor.element.setScrollTop(editor.element.getScrollTop() + 100);
|
||||
t1 = window.performance.now();
|
||||
|
||||
data.push({
|
||||
name: 'Scrolling down after opening a large single-line file',
|
||||
x: sizeInKB,
|
||||
duration: t1 - t0
|
||||
});
|
||||
|
||||
editor.destroy();
|
||||
buffer.destroy();
|
||||
await timeout(10000);
|
||||
}
|
||||
|
||||
workspaceElement.remove();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
function timeout(duration) {
|
||||
return new Promise(resolve => setTimeout(resolve, duration));
|
||||
}
|
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
|
||||
}
|
||||
}
|
601
docs/Pulsar-API-Documentation.md
Normal file
601
docs/Pulsar-API-Documentation.md
Normal file
@ -0,0 +1,601 @@
|
||||
## 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="#css">css</a></dt>
|
||||
<dd><p>This file will manage the updating of <code>autocomplete-css</code> <code>completions.json</code>.
|
||||
We will mainly utilize <code>@webref/css</code>.listAll() function that returns a full CSS
|
||||
list of all properties seperated by their spec shortname. An example
|
||||
of this format is defined below for ease of future modifications.</p>
|
||||
<p> Some important notes about the data contained here:
|
||||
- Often times the <code>value</code> within the <code>property</code> will be in the following format:
|
||||
<code><valueGroupName></code> or even <code><valueGroupName> | value | value2</code> or just <code>value | value2</code>
|
||||
It will be important to build a parser that can handle this format.
|
||||
The <code><valueGroupName></code> then can be realized via that specs <code>values</code> where
|
||||
<code>values[x].name</code> will match the <code><valueGroupName></code>. Another important note about
|
||||
handling values here is that oftentimes <code>values[x].values[]</code> won't actually
|
||||
contain all possible values. And instead this must be handled by checking
|
||||
<code>values[x].value</code> which is another string of <code><valueGroupName> | value</code>.
|
||||
So this should be handled by the same parser.
|
||||
- Additionally an important note is that nowhere in this data do we get any kind
|
||||
of description about the data that could lend a hand in being documentation.
|
||||
So the documentation must be gathered seperatly. Likely the best way to collect
|
||||
our documentation data is via <code>mdn/content</code>.
|
||||
Within <code>content/files/en-us/web/css</code> is a directory of folders titled
|
||||
by the name of properties.</p>
|
||||
<pre><code>The last important thing to note here:
|
||||
MDN doesn't have docs on everything. And that's a good thing. But it means
|
||||
many of our items don't have any kind of description. For this situation
|
||||
we have `manual-property-desc.json` which is a list of manually updated
|
||||
descriptions for properties where there are none. This was a last resort
|
||||
intended to provide the highest quality of completions possible.
|
||||
Overtime many items on this list will likely be able to be removed just as
|
||||
new ones are added. After running the update script you'll see a warning
|
||||
saying how many properties are without completions that would then need to
|
||||
be added to the JSON file.
|
||||
</code></pre>
|
||||
<p> "spec-shortname": {
|
||||
"spec": {
|
||||
"title": "",
|
||||
"url": ""
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "",
|
||||
"value": "",
|
||||
"initial": "",
|
||||
"appliesTo": "",
|
||||
"percentages": "",
|
||||
"computedValue": "",
|
||||
"canonicalOrder": "",
|
||||
"animationType": "",
|
||||
"media": "",
|
||||
"styleDeclaration": [ "", "", "" ]
|
||||
}
|
||||
],
|
||||
"atrules": [
|
||||
{
|
||||
"name": "",
|
||||
"descriptors": [
|
||||
{
|
||||
"name": "",
|
||||
"for": "",
|
||||
"value": "",
|
||||
"type": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"selectors": [],
|
||||
"values": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "",
|
||||
"prose": "Optional description",
|
||||
"value": "",
|
||||
"values": [
|
||||
{
|
||||
"name": "",
|
||||
"prose": "Optional Description",
|
||||
"type": "",
|
||||
"value": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"warnings": []
|
||||
}</p>
|
||||
</dd>
|
||||
<dt><a href="#chromiumElementsShim">chromiumElementsShim</a></dt>
|
||||
<dd><p>This file will manage the updating of <code>autocomplete-html</code> <code>completions.json</code>
|
||||
We will partially utilize <code>@webref/elements</code> <code>.listAll()</code> function that returns
|
||||
a full list of HTML Elements along with a defined <code>interface</code>.
|
||||
To use this <code>interface</code> in any meaningful way, we will utilize the dataset
|
||||
of Attributes that apply to each <code>interface</code> from Chromiums DevTools resource
|
||||
<code>https://github.com/ChromeDevTools/devtools-frontend</code>.
|
||||
Finally from here we will utilize <code>https://github.com/mdn/content</code> to parse
|
||||
the Markdown docs of MDN's website to retreive descriptions for each element.</p>
|
||||
<p> Now for a summary of our <code>completions.json</code> file we aim to generate.
|
||||
There are two top level elements, <code>tags</code> and <code>attributes</code>, both objects.
|
||||
Within <code>tags</code> we expect the following:
|
||||
"tags": {
|
||||
"a": {
|
||||
"attributes": [ "href", "hreflang", "media", "rel", "target", "type" ],
|
||||
"description": "....."
|
||||
}
|
||||
};</p>
|
||||
<p> When an entry contains no <code>attributes</code> there is no empty array, the element
|
||||
simply doesn't exist.</p>
|
||||
<p> The <code>attributes</code> object contains keys of different elements that themselves
|
||||
are objects that can contain several valid keys.</p>
|
||||
<ul>
|
||||
<li>global: Seems to be used exclusively for Global Attributes. Is a boolean
|
||||
which when false, the key does not appear.</li>
|
||||
<li>type: A ?type? for the attribute. It's meaning is not immediately known.
|
||||
Nor a way to reliabley programatically collect it. Some discovered values:</li>
|
||||
</ul>
|
||||
<p>cssStyle: Exclusively used for <code>class</code> attribute
|
||||
boolean: Attributes that only accept <code>true</code> or <code>false</code>
|
||||
flag: For attributes that don't require or accept values. eg autoplay
|
||||
cssId: Exclusively used for the <code>id</code> attribute
|
||||
color: Exclusively used for the <code>bgcolor</code> attribute
|
||||
style: Exclusively used for the <code>style</code> attribute</p>
|
||||
<ul>
|
||||
<li>description: A text description of the attribute</li>
|
||||
<li>attribOption: A string array of valid values that can exist within the attribute.
|
||||
Such as the case with <code>rel</code> where only so many valid options exist.</li>
|
||||
</ul>
|
||||
<p> Although with our data sources mentioned above, we are able to collect nearly
|
||||
all the data needed. Except the <code>type</code> that is defined within our
|
||||
<code>completions.json</code> as well as the <code>attribOption</code> within our completions.</p>
|
||||
<p> Studying these closer reveals that all attributes listing with our <code>completions.json</code>
|
||||
do not appear elsewhere, and are nearly all global attributes.</p>
|
||||
<p> In this case since there is no sane way to collect this data, we will leave this
|
||||
list as a manually maintained section of our <code>completions.json</code>.
|
||||
This does mean that <code>curated-attributes.json</code> is a static document that
|
||||
will require manual updating in the future. Or most ideally, will find a way
|
||||
to automatically generate the needed data.</p>
|
||||
</dd>
|
||||
<dt><a href="#update">update</a></dt>
|
||||
<dd><p>This file aims to run some short simple tests against <code>update.js</code>. Focusing
|
||||
mainly on the Regex used within <code>sanitizeDescription()</code></p>
|
||||
</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="#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="css"></a>
|
||||
|
||||
## css
|
||||
This file will manage the updating of `autocomplete-css` `completions.json`.
|
||||
We will mainly utilize `@webref/css`.listAll() function that returns a full CSS
|
||||
list of all properties seperated by their spec shortname. An example
|
||||
of this format is defined below for ease of future modifications.
|
||||
|
||||
Some important notes about the data contained here:
|
||||
- Often times the `value` within the `property` will be in the following format:
|
||||
`<valueGroupName>` or even `<valueGroupName> | value | value2` or just `value | value2`
|
||||
It will be important to build a parser that can handle this format.
|
||||
The `<valueGroupName>` then can be realized via that specs `values` where
|
||||
`values[x].name` will match the `<valueGroupName>`. Another important note about
|
||||
handling values here is that oftentimes `values[x].values[]` won't actually
|
||||
contain all possible values. And instead this must be handled by checking
|
||||
`values[x].value` which is another string of `<valueGroupName> | value`.
|
||||
So this should be handled by the same parser.
|
||||
- Additionally an important note is that nowhere in this data do we get any kind
|
||||
of description about the data that could lend a hand in being documentation.
|
||||
So the documentation must be gathered seperatly. Likely the best way to collect
|
||||
our documentation data is via `mdn/content`.
|
||||
Within `content/files/en-us/web/css` is a directory of folders titled
|
||||
by the name of properties.
|
||||
|
||||
The last important thing to note here:
|
||||
MDN doesn't have docs on everything. And that's a good thing. But it means
|
||||
many of our items don't have any kind of description. For this situation
|
||||
we have `manual-property-desc.json` which is a list of manually updated
|
||||
descriptions for properties where there are none. This was a last resort
|
||||
intended to provide the highest quality of completions possible.
|
||||
Overtime many items on this list will likely be able to be removed just as
|
||||
new ones are added. After running the update script you'll see a warning
|
||||
saying how many properties are without completions that would then need to
|
||||
be added to the JSON file.
|
||||
|
||||
"spec-shortname": {
|
||||
"spec": {
|
||||
"title": "",
|
||||
"url": ""
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "",
|
||||
"value": "",
|
||||
"initial": "",
|
||||
"appliesTo": "",
|
||||
"percentages": "",
|
||||
"computedValue": "",
|
||||
"canonicalOrder": "",
|
||||
"animationType": "",
|
||||
"media": "",
|
||||
"styleDeclaration": [ "", "", "" ]
|
||||
}
|
||||
],
|
||||
"atrules": [
|
||||
{
|
||||
"name": "",
|
||||
"descriptors": [
|
||||
{
|
||||
"name": "",
|
||||
"for": "",
|
||||
"value": "",
|
||||
"type": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"selectors": [],
|
||||
"values": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "",
|
||||
"prose": "Optional description",
|
||||
"value": "",
|
||||
"values": [
|
||||
{
|
||||
"name": "",
|
||||
"prose": "Optional Description",
|
||||
"type": "",
|
||||
"value": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"warnings": []
|
||||
}
|
||||
|
||||
**Kind**: global constant
|
||||
<a name="chromiumElementsShim"></a>
|
||||
|
||||
## chromiumElementsShim
|
||||
This file will manage the updating of `autocomplete-html` `completions.json`
|
||||
We will partially utilize `@webref/elements` `.listAll()` function that returns
|
||||
a full list of HTML Elements along with a defined `interface`.
|
||||
To use this `interface` in any meaningful way, we will utilize the dataset
|
||||
of Attributes that apply to each `interface` from Chromiums DevTools resource
|
||||
`https://github.com/ChromeDevTools/devtools-frontend`.
|
||||
Finally from here we will utilize `https://github.com/mdn/content` to parse
|
||||
the Markdown docs of MDN's website to retreive descriptions for each element.
|
||||
|
||||
Now for a summary of our `completions.json` file we aim to generate.
|
||||
There are two top level elements, `tags` and `attributes`, both objects.
|
||||
Within `tags` we expect the following:
|
||||
"tags": {
|
||||
"a": {
|
||||
"attributes": [ "href", "hreflang", "media", "rel", "target", "type" ],
|
||||
"description": "....."
|
||||
}
|
||||
};
|
||||
|
||||
When an entry contains no `attributes` there is no empty array, the element
|
||||
simply doesn't exist.
|
||||
|
||||
The `attributes` object contains keys of different elements that themselves
|
||||
are objects that can contain several valid keys.
|
||||
- global: Seems to be used exclusively for Global Attributes. Is a boolean
|
||||
which when false, the key does not appear.
|
||||
- type: A ?type? for the attribute. It's meaning is not immediately known.
|
||||
Nor a way to reliabley programatically collect it. Some discovered values:
|
||||
cssStyle: Exclusively used for `class` attribute
|
||||
boolean: Attributes that only accept `true` or `false`
|
||||
flag: For attributes that don't require or accept values. eg autoplay
|
||||
cssId: Exclusively used for the `id` attribute
|
||||
color: Exclusively used for the `bgcolor` attribute
|
||||
style: Exclusively used for the `style` attribute
|
||||
- description: A text description of the attribute
|
||||
- attribOption: A string array of valid values that can exist within the attribute.
|
||||
Such as the case with `rel` where only so many valid options exist.
|
||||
|
||||
Although with our data sources mentioned above, we are able to collect nearly
|
||||
all the data needed. Except the `type` that is defined within our
|
||||
`completions.json` as well as the `attribOption` within our completions.
|
||||
|
||||
Studying these closer reveals that all attributes listing with our `completions.json`
|
||||
do not appear elsewhere, and are nearly all global attributes.
|
||||
|
||||
In this case since there is no sane way to collect this data, we will leave this
|
||||
list as a manually maintained section of our `completions.json`.
|
||||
This does mean that `curated-attributes.json` is a static document that
|
||||
will require manual updating in the future. Or most ideally, will find a way
|
||||
to automatically generate the needed data.
|
||||
|
||||
**Kind**: global constant
|
||||
<a name="update"></a>
|
||||
|
||||
## update
|
||||
This file aims to run some short simple tests against `update.js`. Focusing
|
||||
mainly on the Regex used within `sanitizeDescription()`
|
||||
|
||||
**Kind**: global constant
|
||||
<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="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**:
|
609
docs/Source-Code-Documentation.md
Normal file
609
docs/Source-Code-Documentation.md
Normal file
@ -0,0 +1,609 @@
|
||||
## 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="#css">css</a></dt>
|
||||
<dd><p>This file will manage the updating of <code>autocomplete-css</code> <code>completions.json</code>.
|
||||
We will mainly utilize <code>@webref/css</code>.listAll() function that returns a full CSS
|
||||
list of all properties seperated by their spec shortname. An example
|
||||
of this format is defined below for ease of future modifications.</p>
|
||||
<p> Some important notes about the data contained here:
|
||||
- Often times the <code>value</code> within the <code>property</code> will be in the following format:
|
||||
<code><valueGroupName></code> or even <code><valueGroupName> | value | value2</code> or just <code>value | value2</code>
|
||||
It will be important to build a parser that can handle this format.
|
||||
The <code><valueGroupName></code> then can be realized via that specs <code>values</code> where
|
||||
<code>values[x].name</code> will match the <code><valueGroupName></code>. Another important note about
|
||||
handling values here is that oftentimes <code>values[x].values[]</code> won't actually
|
||||
contain all possible values. And instead this must be handled by checking
|
||||
<code>values[x].value</code> which is another string of <code><valueGroupName> | value</code>.
|
||||
So this should be handled by the same parser.
|
||||
- Additionally an important note is that nowhere in this data do we get any kind
|
||||
of description about the data that could lend a hand in being documentation.
|
||||
So the documentation must be gathered seperatly. Likely the best way to collect
|
||||
our documentation data is via <code>mdn/content</code>.
|
||||
Within <code>content/files/en-us/web/css</code> is a directory of folders titled
|
||||
by the name of properties.</p>
|
||||
<pre><code>The last important thing to note here:
|
||||
MDN doesn't have docs on everything. And that's a good thing. But it means
|
||||
many of our items don't have any kind of description. For this situation
|
||||
we have `manual-property-desc.json` which is a list of manually updated
|
||||
descriptions for properties where there are none. This was a last resort
|
||||
intended to provide the highest quality of completions possible.
|
||||
Overtime many items on this list will likely be able to be removed just as
|
||||
new ones are added. After running the update script you'll see a warning
|
||||
saying how many properties are without completions that would then need to
|
||||
be added to the JSON file.
|
||||
</code></pre>
|
||||
<p> "spec-shortname": {
|
||||
"spec": {
|
||||
"title": "",
|
||||
"url": ""
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "",
|
||||
"value": "",
|
||||
"initial": "",
|
||||
"appliesTo": "",
|
||||
"percentages": "",
|
||||
"computedValue": "",
|
||||
"canonicalOrder": "",
|
||||
"animationType": "",
|
||||
"media": "",
|
||||
"styleDeclaration": [ "", "", "" ]
|
||||
}
|
||||
],
|
||||
"atrules": [
|
||||
{
|
||||
"name": "",
|
||||
"descriptors": [
|
||||
{
|
||||
"name": "",
|
||||
"for": "",
|
||||
"value": "",
|
||||
"type": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"selectors": [],
|
||||
"values": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "",
|
||||
"prose": "Optional description",
|
||||
"value": "",
|
||||
"values": [
|
||||
{
|
||||
"name": "",
|
||||
"prose": "Optional Description",
|
||||
"type": "",
|
||||
"value": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"warnings": []
|
||||
}</p>
|
||||
</dd>
|
||||
<dt><a href="#chromiumElementsShim">chromiumElementsShim</a></dt>
|
||||
<dd><p>This file will manage the updating of <code>autocomplete-html</code> <code>completions.json</code>
|
||||
We will partially utilize <code>@webref/elements</code> <code>.listAll()</code> function that returns
|
||||
a full list of HTML Elements along with a defined <code>interface</code>.
|
||||
To use this <code>interface</code> in any meaningful way, we will utilize the dataset
|
||||
of Attributes that apply to each <code>interface</code> from Chromiums DevTools resource
|
||||
<code>https://github.com/ChromeDevTools/devtools-frontend</code>.
|
||||
Finally from here we will utilize <code>https://github.com/mdn/content</code> to parse
|
||||
the Markdown docs of MDN's website to retreive descriptions for each element.</p>
|
||||
<p> Now for a summary of our <code>completions.json</code> file we aim to generate.
|
||||
There are two top level elements, <code>tags</code> and <code>attributes</code>, both objects.
|
||||
Within <code>tags</code> we expect the following:
|
||||
"tags": {
|
||||
"a": {
|
||||
"attributes": [ "href", "hreflang", "media", "rel", "target", "type" ],
|
||||
"description": "....."
|
||||
}
|
||||
};</p>
|
||||
<p> When an entry contains no <code>attributes</code> there is no empty array, the element
|
||||
simply doesn't exist.</p>
|
||||
<p> The <code>attributes</code> object contains keys of different elements that themselves
|
||||
are objects that can contain several valid keys.</p>
|
||||
<ul>
|
||||
<li>global: Seems to be used exclusively for Global Attributes. Is a boolean
|
||||
which when false, the key does not appear.</li>
|
||||
<li>type: A ?type? for the attribute. It's meaning is not immediately known.
|
||||
Nor a way to reliabley programatically collect it. Some discovered values:</li>
|
||||
</ul>
|
||||
<p>cssStyle: Exclusively used for <code>class</code> attribute
|
||||
boolean: Attributes that only accept <code>true</code> or <code>false</code>
|
||||
flag: For attributes that don't require or accept values. eg autoplay
|
||||
cssId: Exclusively used for the <code>id</code> attribute
|
||||
color: Exclusively used for the <code>bgcolor</code> attribute
|
||||
style: Exclusively used for the <code>style</code> attribute</p>
|
||||
<ul>
|
||||
<li>description: A text description of the attribute</li>
|
||||
<li>attribOption: A string array of valid values that can exist within the attribute.
|
||||
Such as the case with <code>rel</code> where only so many valid options exist.</li>
|
||||
</ul>
|
||||
<p> Although with our data sources mentioned above, we are able to collect nearly
|
||||
all the data needed. Except the <code>type</code> that is defined within our
|
||||
<code>completions.json</code> as well as the <code>attribOption</code> within our completions.</p>
|
||||
<p> Studying these closer reveals that all attributes listing with our <code>completions.json</code>
|
||||
do not appear elsewhere, and are nearly all global attributes.</p>
|
||||
<p> In this case since there is no sane way to collect this data, we will leave this
|
||||
list as a manually maintained section of our <code>completions.json</code>.
|
||||
This does mean that <code>curated-attributes.json</code> is a static document that
|
||||
will require manual updating in the future. Or most ideally, will find a way
|
||||
to automatically generate the needed data.</p>
|
||||
</dd>
|
||||
<dt><a href="#update">update</a></dt>
|
||||
<dd><p>This file aims to run some short simple tests against <code>update.js</code>. Focusing
|
||||
mainly on the Regex used within <code>sanitizeDescription()</code></p>
|
||||
</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="#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="css"></a>
|
||||
|
||||
## css
|
||||
This file will manage the updating of `autocomplete-css` `completions.json`.
|
||||
We will mainly utilize `@webref/css`.listAll() function that returns a full CSS
|
||||
list of all properties seperated by their spec shortname. An example
|
||||
of this format is defined below for ease of future modifications.
|
||||
|
||||
Some important notes about the data contained here:
|
||||
- Often times the `value` within the `property` will be in the following format:
|
||||
`<valueGroupName>` or even `<valueGroupName> | value | value2` or just `value | value2`
|
||||
It will be important to build a parser that can handle this format.
|
||||
The `<valueGroupName>` then can be realized via that specs `values` where
|
||||
`values[x].name` will match the `<valueGroupName>`. Another important note about
|
||||
handling values here is that oftentimes `values[x].values[]` won't actually
|
||||
contain all possible values. And instead this must be handled by checking
|
||||
`values[x].value` which is another string of `<valueGroupName> | value`.
|
||||
So this should be handled by the same parser.
|
||||
- Additionally an important note is that nowhere in this data do we get any kind
|
||||
of description about the data that could lend a hand in being documentation.
|
||||
So the documentation must be gathered seperatly. Likely the best way to collect
|
||||
our documentation data is via `mdn/content`.
|
||||
Within `content/files/en-us/web/css` is a directory of folders titled
|
||||
by the name of properties.
|
||||
|
||||
The last important thing to note here:
|
||||
MDN doesn't have docs on everything. And that's a good thing. But it means
|
||||
many of our items don't have any kind of description. For this situation
|
||||
we have `manual-property-desc.json` which is a list of manually updated
|
||||
descriptions for properties where there are none. This was a last resort
|
||||
intended to provide the highest quality of completions possible.
|
||||
Overtime many items on this list will likely be able to be removed just as
|
||||
new ones are added. After running the update script you'll see a warning
|
||||
saying how many properties are without completions that would then need to
|
||||
be added to the JSON file.
|
||||
|
||||
"spec-shortname": {
|
||||
"spec": {
|
||||
"title": "",
|
||||
"url": ""
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "",
|
||||
"value": "",
|
||||
"initial": "",
|
||||
"appliesTo": "",
|
||||
"percentages": "",
|
||||
"computedValue": "",
|
||||
"canonicalOrder": "",
|
||||
"animationType": "",
|
||||
"media": "",
|
||||
"styleDeclaration": [ "", "", "" ]
|
||||
}
|
||||
],
|
||||
"atrules": [
|
||||
{
|
||||
"name": "",
|
||||
"descriptors": [
|
||||
{
|
||||
"name": "",
|
||||
"for": "",
|
||||
"value": "",
|
||||
"type": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"selectors": [],
|
||||
"values": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "",
|
||||
"prose": "Optional description",
|
||||
"value": "",
|
||||
"values": [
|
||||
{
|
||||
"name": "",
|
||||
"prose": "Optional Description",
|
||||
"type": "",
|
||||
"value": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"warnings": []
|
||||
}
|
||||
|
||||
**Kind**: global constant
|
||||
<a name="chromiumElementsShim"></a>
|
||||
|
||||
## chromiumElementsShim
|
||||
This file will manage the updating of `autocomplete-html` `completions.json`
|
||||
We will partially utilize `@webref/elements` `.listAll()` function that returns
|
||||
a full list of HTML Elements along with a defined `interface`.
|
||||
To use this `interface` in any meaningful way, we will utilize the dataset
|
||||
of Attributes that apply to each `interface` from Chromiums DevTools resource
|
||||
`https://github.com/ChromeDevTools/devtools-frontend`.
|
||||
Finally from here we will utilize `https://github.com/mdn/content` to parse
|
||||
the Markdown docs of MDN's website to retreive descriptions for each element.
|
||||
|
||||
Now for a summary of our `completions.json` file we aim to generate.
|
||||
There are two top level elements, `tags` and `attributes`, both objects.
|
||||
Within `tags` we expect the following:
|
||||
"tags": {
|
||||
"a": {
|
||||
"attributes": [ "href", "hreflang", "media", "rel", "target", "type" ],
|
||||
"description": "....."
|
||||
}
|
||||
};
|
||||
|
||||
When an entry contains no `attributes` there is no empty array, the element
|
||||
simply doesn't exist.
|
||||
|
||||
The `attributes` object contains keys of different elements that themselves
|
||||
are objects that can contain several valid keys.
|
||||
- global: Seems to be used exclusively for Global Attributes. Is a boolean
|
||||
which when false, the key does not appear.
|
||||
- type: A ?type? for the attribute. It's meaning is not immediately known.
|
||||
Nor a way to reliabley programatically collect it. Some discovered values:
|
||||
cssStyle: Exclusively used for `class` attribute
|
||||
boolean: Attributes that only accept `true` or `false`
|
||||
flag: For attributes that don't require or accept values. eg autoplay
|
||||
cssId: Exclusively used for the `id` attribute
|
||||
color: Exclusively used for the `bgcolor` attribute
|
||||
style: Exclusively used for the `style` attribute
|
||||
- description: A text description of the attribute
|
||||
- attribOption: A string array of valid values that can exist within the attribute.
|
||||
Such as the case with `rel` where only so many valid options exist.
|
||||
|
||||
Although with our data sources mentioned above, we are able to collect nearly
|
||||
all the data needed. Except the `type` that is defined within our
|
||||
`completions.json` as well as the `attribOption` within our completions.
|
||||
|
||||
Studying these closer reveals that all attributes listing with our `completions.json`
|
||||
do not appear elsewhere, and are nearly all global attributes.
|
||||
|
||||
In this case since there is no sane way to collect this data, we will leave this
|
||||
list as a manually maintained section of our `completions.json`.
|
||||
This does mean that `curated-attributes.json` is a static document that
|
||||
will require manual updating in the future. Or most ideally, will find a way
|
||||
to automatically generate the needed data.
|
||||
|
||||
**Kind**: global constant
|
||||
<a name="update"></a>
|
||||
|
||||
## update
|
||||
This file aims to run some short simple tests against `update.js`. Focusing
|
||||
mainly on the Regex used within `sanitizeDescription()`
|
||||
|
||||
**Kind**: global constant
|
||||
<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="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**:
|
@ -1,11 +0,0 @@
|
||||
# Your init script
|
||||
#
|
||||
# Pulsar will evaluate this file each time a new window is opened. It is run
|
||||
# after packages are loaded/activated and after the previous editor state
|
||||
# has been restored.
|
||||
#
|
||||
# An example hack to log to the console when each text editor is saved.
|
||||
#
|
||||
# atom.workspace.observeTextEditors (editor) ->
|
||||
# editor.onDidSave ->
|
||||
# console.log "Saved! #{editor.getPath()}"
|
17
dot-atom/init.js
Normal file
17
dot-atom/init.js
Normal file
@ -0,0 +1,17 @@
|
||||
// Your init script
|
||||
//
|
||||
// Pulsar will evaluate this file each time a new window is opened. It is run
|
||||
// after packages are loaded/activated and after the previous editor state
|
||||
// has been restored.
|
||||
//
|
||||
// An example hack to log to the console when each text editor is saved.
|
||||
//
|
||||
// atom.workspace.observeTextEditors(editor =>
|
||||
// editor.onDidSave(() =>
|
||||
// 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
|
@ -7,14 +7,18 @@ const { expect } = require('@playwright/test')
|
||||
async function openAtom(profilePath, videoName) {
|
||||
const env = process.env
|
||||
env.ATOM_HOME = path.join("tmp", profilePath)
|
||||
env.APM_PATH = path.join("apm", "node_modules", "pulsar-package-manager", "bin", "apm")
|
||||
|
||||
const config = {
|
||||
args: ["--no-sandbox", "."],
|
||||
cwd: ".",
|
||||
env: env,
|
||||
timeout: 10000
|
||||
timeout: 50000
|
||||
}
|
||||
if(env.BINARY_NAME) {
|
||||
config.executablePath = env.BINARY_NAME
|
||||
config.args = ["--no-sandbox"]
|
||||
}
|
||||
|
||||
if(process.env.CI) {
|
||||
config.recordVideo = {
|
||||
dir: path.join('tests', 'videos', videoName)
|
||||
|
@ -52,24 +52,32 @@ test.describe('Opening Atom for the first time', () => {
|
||||
|
||||
test('the editor opens at the welcome page', async () => {
|
||||
const workspace = editor.page.locator('atom-workspace')
|
||||
await expect(workspace).toHaveText(/A hackable text editor/, {
|
||||
await expect(workspace).toHaveText(/A Community-led Hyper-Hackable Text Editor/, {
|
||||
useInnerText: true,
|
||||
})
|
||||
})
|
||||
|
||||
// FIXME: mock backend, Atom's servers are unreliable!
|
||||
// test('allows to search for packages', async () => {
|
||||
// await runCommand(editor, 'Settings View: Open')
|
||||
// await editor.page.locator('a.icon', { hasText: 'Install' }).click()
|
||||
// await typeInEditor(editor, '.packages', "language-javascript")
|
||||
// await expect(editor.page.locator('.package-name', { hasText: 'language-javascript' }).first())
|
||||
// .toBeVisible()
|
||||
// })
|
||||
//test('shows core packages', async () => {
|
||||
// await runCommand(editor, 'Settings View: Open')
|
||||
// await editor.page.locator('a.icon', { hasText: 'Packages' }).click()
|
||||
// await expect(editor.page.locator('.package-name', { hasText: 'about' }).first())
|
||||
// .toBeVisible()
|
||||
//})
|
||||
|
||||
//test('allows to install for packages', async () => {
|
||||
// await runCommand(editor, 'Settings View: Open')
|
||||
// await editor.page.locator('a.icon', { hasText: 'Install' }).click()
|
||||
// await typeInEditor(editor, '.packages', "termination")
|
||||
// await editor.page.locator('button.install-button:visible', { hasText: 'Install' }).click()
|
||||
// test.setTimeout(120000);
|
||||
// await expect(editor.page.locator('button', { hasText: 'Settings' }).first())
|
||||
// .toBeVisible({ timeout: 120000 })
|
||||
//})
|
||||
|
||||
test.describe('the editor have syntax highlight', async () => {
|
||||
test.beforeAll(async () => {
|
||||
const workspace = editor.page.locator('atom-workspace')
|
||||
await expect(workspace).toHaveText(/A hackable text editor/, {
|
||||
await expect(workspace).toHaveText(/A Community-led Hyper-Hackable Text Editor/, {
|
||||
useInnerText: true,
|
||||
})
|
||||
await runCommand(editor, 'Tabs: Close All Tabs')
|
||||
|
@ -155,7 +155,6 @@
|
||||
{ label: 'Open In Dev Mode…', command: 'application:open-dev' }
|
||||
{ label: 'Reload Window', command: 'window:reload' }
|
||||
{ label: 'Run Package Specs', command: 'window:run-package-specs' }
|
||||
{ label: 'Run Benchmarks', command: 'window:run-benchmarks' }
|
||||
{ label: 'Toggle Developer Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
}
|
||||
|
@ -138,7 +138,6 @@
|
||||
{ label: 'Open In &Dev Mode…', command: 'application:open-dev' }
|
||||
{ label: '&Reload Window', command: 'window:reload' }
|
||||
{ label: 'Run Package &Specs', command: 'window:run-package-specs' }
|
||||
{ label: 'Run &Benchmarks', command: 'window:run-benchmarks' }
|
||||
{ label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
}
|
||||
|
@ -137,7 +137,6 @@
|
||||
{ label: 'Open In &Dev Mode…', command: 'application:open-dev' }
|
||||
{ label: '&Reload Window', command: 'window:reload' }
|
||||
{ label: 'Run Package &Specs', command: 'window:run-package-specs' }
|
||||
{ label: 'Run &Benchmarks', command: 'window:run-benchmarks' }
|
||||
{ label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
}
|
||||
|
11628
package-lock.json
generated
11628
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
159
package.json
159
package.json
@ -1,14 +1,15 @@
|
||||
{
|
||||
"name": "pulsar",
|
||||
"author": "Pulsar Community <noreply@pulsar-edit.com>",
|
||||
"author": "Pulsar-Edit <admin@pulsar-edit.dev>",
|
||||
"productName": "Pulsar",
|
||||
"version": "1.63.0-dev",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"version": "1.103.0-dev",
|
||||
"description": "A Community-led Hyper-Hackable Text Editor",
|
||||
"branding": {
|
||||
"id": "pulsar",
|
||||
"name": "Pulsar",
|
||||
"urlWeb": "https://atom.io/",
|
||||
"urlGH": "https://github.com/pulsar-edit"
|
||||
"urlWeb": "https://pulsar-edit.dev/",
|
||||
"urlGH": "https://github.com/pulsar-edit",
|
||||
"urlForum": "https://github.com/orgs/pulsar-edit/discussions"
|
||||
},
|
||||
"main": "./src/main-process/main.js",
|
||||
"repository": {
|
||||
@ -24,7 +25,7 @@
|
||||
"@atom/fuzzy-native": "^1.2.1",
|
||||
"@babel/core": "7.18.6",
|
||||
"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",
|
||||
@ -33,57 +34,53 @@
|
||||
"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",
|
||||
"autosave": "file:./packages/autosave",
|
||||
"babel-preset-atomic": "^5.0.0",
|
||||
"background-tips": "https://codeload.github.com/atom/background-tips/legacy.tar.gz/refs/tags/v0.28.0",
|
||||
"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://codeload.github.com/atom/bracket-matcher/legacy.tar.gz/refs/tags/v0.92.0",
|
||||
"bookmarks": "file:packages/bookmarks",
|
||||
"bracket-matcher": "file:packages/bracket-matcher",
|
||||
"chai": "4.3.4",
|
||||
"chart.js": "2.9.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",
|
||||
"document-register-element": "https://github.com/pulsar-edit/document-register-element.git#1f5868f",
|
||||
"encoding-selector": "file:packages/encoding-selector",
|
||||
"etch": "0.14.1",
|
||||
"event-kit": "^2.5.3",
|
||||
"exception-reporting": "file:packages/exception-reporting",
|
||||
"find-and-replace": "https://github.com/atom-community/find-and-replace/archive/refs/tags/v0.220.1.tar.gz",
|
||||
"find-parent-dir": "^0.3.0",
|
||||
"first-mate": "7.4.3",
|
||||
"second-mate": "https://github.com/pulsar-edit/second-mate.git#14aa7bd",
|
||||
"focus-trap": "6.3.0",
|
||||
"fs-admin": "0.19.0",
|
||||
"fs-plus": "^3.1.1",
|
||||
"fstream": "1.0.12",
|
||||
"fuzzaldrin": "^2.1",
|
||||
"fuzzy-finder": "https://codeload.github.com/atom/fuzzy-finder/legacy.tar.gz/refs/tags/v1.14.3",
|
||||
"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",
|
||||
"jasmine-tagged": "^1.1.4",
|
||||
"key-path-helpers": "^0.4.0",
|
||||
"keybinding-resolver": "https://codeload.github.com/atom/keybinding-resolver/legacy.tar.gz/refs/tags/v0.39.1",
|
||||
"keybinding-resolver": "file:./packages/keybinding-resolver",
|
||||
"language-c": "file:packages/language-c",
|
||||
"language-clojure": "file:packages/language-clojure",
|
||||
"language-coffee-script": "file:packages/language-coffee-script",
|
||||
@ -122,7 +119,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",
|
||||
@ -136,45 +133,45 @@
|
||||
"one-dark-ui": "file:packages/one-dark-ui",
|
||||
"one-light-syntax": "file:packages/one-light-syntax",
|
||||
"one-light-ui": "file:packages/one-light-ui",
|
||||
"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",
|
||||
"open-on-github": "file:packages/open-on-github",
|
||||
"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.9",
|
||||
"settings-view": "file:packages/settings-view",
|
||||
"sinon": "9.2.1",
|
||||
"snippets": "https://github.com/atom-community/snippets/archive/cdde11928c19d4969aba9a8dc5b1030ab68c4be2.tar.gz",
|
||||
"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",
|
||||
"superstring": "https://github.com/pulsar-edit/superstring.git#708924046f8db9d05901a5372337f249ff5c47bb",
|
||||
"status-bar": "file:packages/status-bar",
|
||||
"styleguide": "file:./packages/styleguide",
|
||||
"superstring": "^2.4.4",
|
||||
"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",
|
||||
"text-buffer": "https://github.com/pulsar-edit/text-buffer.git#738c797a5aab45ca78c383e29fa545984e0a2977",
|
||||
"tree-sitter": "https://github.com/pulsar-edit/node-tree-sitter.git#c304335",
|
||||
"timecop": "https://codeload.github.com/atom/timecop/legacy.tar.gz/refs/tags/v0.36.2",
|
||||
"tabs": "file:packages/tabs",
|
||||
"temp": "0.9.4",
|
||||
"text-buffer": "^13.18.6",
|
||||
"timecop": "file:./packages/timecop",
|
||||
"tree-sitter": "0.20.0",
|
||||
"tree-view": "https://codeload.github.com/atom/tree-view/legacy.tar.gz/refs/tags/v0.229.1",
|
||||
"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",
|
||||
"whitespace": "file:./packages/whitespace",
|
||||
"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 +187,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",
|
||||
"bracket-matcher": "0.92.0",
|
||||
"command-palette": "0.43.5",
|
||||
"autosave": "file:./packages/autosave",
|
||||
"background-tips": "file:./packages/background-tips",
|
||||
"bookmarks": "file:./packages/bookmarks",
|
||||
"bracket-matcher": "file:./packages/bracket-matcher",
|
||||
"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",
|
||||
"keybinding-resolver": "file:./packages/keybinding-resolver",
|
||||
"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",
|
||||
"snippets": "1.6.0",
|
||||
"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",
|
||||
"timecop": "0.36.2",
|
||||
"tabs": "file:./packages/tabs",
|
||||
"timecop": "file:./packages/timecop",
|
||||
"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",
|
||||
"whitespace": "file:./packages/whitespace",
|
||||
"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 +268,23 @@
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "node -e 'process.exit(0)'",
|
||||
"test": "node script/test",
|
||||
"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",
|
||||
"snapshotResult"
|
||||
]
|
||||
"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": "13.6.9",
|
||||
"electron-builder": "23.3.1",
|
||||
"electron-rebuild": "3.2.7",
|
||||
"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",
|
||||
|
@ -1,167 +1,112 @@
|
||||
# Atom Core Packages
|
||||
# Core Packages
|
||||
|
||||
This folder contains core packages that are bundled with Atom releases. Not all Atom core packages are kept here; please
|
||||
see the table below for the location of every core Atom package.
|
||||
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 |
|
||||
|---------|------------------|-----------------|
|
||||
| **about** | [`./about`](./about) | [#17832](https://github.com/atom/atom/issues/17832) |
|
||||
| **atom-dark-syntax** | [`./atom-dark-syntax`](./atom-dark-syntax) | [#17849](https://github.com/atom/atom/issues/17849) |
|
||||
| **atom-dark-ui** | [`./atom-dark-ui`](./atom-dark-ui) | [#17850](https://github.com/atom/atom/issues/17850) |
|
||||
| **atom-light-syntax** | [`./atom-light-syntax`](./atom-light-syntax) | [#17851](https://github.com/atom/atom/issues/17851) |
|
||||
| **atom-light-ui** | [`./atom-light-ui`](./atom-light-ui) | [#17852](https://github.com/atom/atom/issues/17852) |
|
||||
| **about** | [`./about`](./about) | |
|
||||
| **atom-dark-syntax** | [`./atom-dark-syntax`](./atom-dark-syntax) | |
|
||||
| **atom-dark-ui** | [`./atom-dark-ui`](./atom-dark-ui) | |
|
||||
| **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] | |
|
||||
| **autoflow** | [`./autoflow`](./autoflow) | [#17833](https://github.com/atom/atom/issues/17833) |
|
||||
| **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) |
|
||||
| **base16-tomorrow-dark-theme** | [`./base16-tomorrow-dark-theme`](./base16-tomorrow-dark-theme) | [#17836](https://github.com/atom/atom/issues/17836) |
|
||||
| **base16-tomorrow-light-theme** | [`./base16-tomorrow-light-theme`](./base16-tomorrow-light-theme) | [#17837](https://github.com/atom/atom/issues/17837) |
|
||||
| **bookmarks** | [`atom/bookmarks`][bookmarks] | [#18273](https://github.com/atom/atom/issues/18273) |
|
||||
| **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) |
|
||||
| **deprecation-cop** | [`./deprecation-cop`](./deprecation-cop) | [#17839](https://github.com/atom/atom/issues/17839) |
|
||||
| **dev-live-reload** | [`./dev-live-reload`](dev-live-reload) | [#17840](https://github.com/atom/atom/issues/17840) |
|
||||
| **encoding-selector** | [`atom/encoding-selector`][encoding-selector] | [#17841](https://github.com/atom/atom/issues/17841) |
|
||||
| **exception-reporting** | [`./exception-reporting`](./exception-reporting) | [#17842](https://github.com/atom/atom/issues/17842) |
|
||||
| **find-and-replace** | [`atom/find-and-replace`][find-and-replace] | |
|
||||
| **fuzzy-finder** | [`atom/fuzzy-finder`][fuzzy-finder] | |
|
||||
| **github** | [`atom/github`][github] | |
|
||||
| **git-diff** | [`./git-diff`](./git-diff) | [#17843](https://github.com/atom/atom/issues/17843) |
|
||||
| **go-to-line** | [`./go-to-line`](./go-to-line) | [#17844](https://github.com/atom/atom/issues/17844) |
|
||||
| **grammar-selector** | [`./grammar-selector`](./grammar-selector) | [#17845](https://github.com/atom/atom/issues/17845) |
|
||||
| **image-view** | [`atom/image-view`][image-view] | [#18274](https://github.com/atom/atom/issues/18274) |
|
||||
| **incompatible-packages** | [`./incompatible-packages`](./incompatible-packages) | [#17846](https://github.com/atom/atom/issues/17846) |
|
||||
| **keybinding-resolver** | [`atom/keybinding-resolver`][keybinding-resolver] | [#18275](https://github.com/atom/atom/issues/18275) |
|
||||
| **language-c** | [`atom/language-c`](./language-c) | |
|
||||
| **language-clojure** | [`atom/language-clojure`](./language-clojure) | |
|
||||
| **language-coffee-script** | [`atom/language-coffee-script`](./language-coffee-script) | |
|
||||
| **language-csharp** | [`atom/language-csharp`](./language-csharp) | |
|
||||
| **language-css** | [`atom/language-css`](./language-css) | |
|
||||
| **language-gfm** | [`atom/language-gfm`](./language-gfm) | |
|
||||
| **language-git** | [`atom/language-git`](./language-git) | |
|
||||
| **language-go** | [`atom/language-go`](./language-go) | |
|
||||
| **language-html** | [`atom/language-html`](./language-html) | |
|
||||
| **language-hyperlink** | [`atom/language-hyperlink`](./language-hyperlink) | |
|
||||
| **language-java** | [`atom/language-java`](./language-java) | |
|
||||
| **language-javascript** | [`atom/language-javascript`](./language-javascript) | |
|
||||
| **language-json** | [`atom/language-json`](./language-json) | |
|
||||
| **language-less** | [`atom/language-less`](./language-less) | |
|
||||
| **language-make** | [`atom/language-make`](./language-make) | |
|
||||
| **language-mustache** | [`atom/language-mustache`](./language-mustache) | |
|
||||
| **language-objective-c** | [`atom/language-objective-c`](./language-objective-c) | |
|
||||
| **language-perl** | [`atom/language-perl`](./language-perl) | |
|
||||
| **language-php** | [`atom/language-php`](./language-php) | |
|
||||
| **language-property-list** | [`atom/language-property-list`](./language-property-list) | |
|
||||
| **language-python** | [`atom/language-python`](./language-python) | |
|
||||
| **language-ruby** | [`atom/language-ruby`](./language-ruby) | |
|
||||
| **language-ruby-on-rails** | [`atom/language-ruby-on-rails`](./language-ruby-on-rails) | |
|
||||
| **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** | [`./autosave`](./autosave) | |
|
||||
| **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** | [`./bookmarks`](./bookmarks) | |
|
||||
| **bracket-matcher** | [`./bracket-matcher`](./bracket-matcher) | |
|
||||
| **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** | [`./encoding-selector`](./encoding-selector) | |
|
||||
| **exception-reporting** | [`./exception-reporting`](./exception-reporting) | |
|
||||
| **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** | [`./image-view`](./image-view) | |
|
||||
| **incompatible-packages** | [`./incompatible-packages`](./incompatible-packages) | |
|
||||
| **keybinding-resolver** | [`./keybinding-resolver`](./keybinding-resolver) | |
|
||||
| **language-c** | [`./language-c`](./language-c) | |
|
||||
| **language-clojure** | [`./language-clojure`](./language-clojure) | |
|
||||
| **language-coffee-script** | [`./language-coffee-script`](./language-coffee-script) | |
|
||||
| **language-csharp** | [`./language-csharp`](./language-csharp) | |
|
||||
| **language-css** | [`./language-css`](./language-css) | |
|
||||
| **language-gfm** | [`./language-gfm`](./language-gfm) | |
|
||||
| **language-git** | [`./language-git`](./language-git) | |
|
||||
| **language-go** | [`./language-go`](./language-go) | |
|
||||
| **language-html** | [`./language-html`](./language-html) | |
|
||||
| **language-hyperlink** | [`./language-hyperlink`](./language-hyperlink) | |
|
||||
| **language-java** | [`./language-java`](./language-java) | |
|
||||
| **language-javascript** | [`./language-javascript`](./language-javascript) | |
|
||||
| **language-json** | [`./language-json`](./language-json) | |
|
||||
| **language-less** | [`./language-less`](./language-less) | |
|
||||
| **language-make** | [`./language-make`](./language-make) | |
|
||||
| **language-mustache** | [`./language-mustache`](./language-mustache) | |
|
||||
| **language-objective-c** | [`./language-objective-c`](./language-objective-c) | |
|
||||
| **language-perl** | [`./language-perl`](./language-perl) | |
|
||||
| **language-php** | [`./language-php`](./language-php) | |
|
||||
| **language-property-list** | [`./language-property-list`](./language-property-list) | |
|
||||
| **language-python** | [`./language-python`](./language-python) | |
|
||||
| **language-ruby** | [`./language-ruby`](./language-ruby) | |
|
||||
| **language-ruby-on-rails** | [`./language-ruby-on-rails`](./language-ruby-on-rails) | |
|
||||
| **language-rust-bundled** | [`./language-rust-bundled`](./language-rust-bundled) | |
|
||||
| **language-sass** | [`atom/language-sass`](./language-sass) | |
|
||||
| **language-shellscript** | [`atom/language-shellscript`](./language-shellscript) | |
|
||||
| **language-source** | [`atom/language-source`](./language-source) | |
|
||||
| **language-sql** | [`atom/language-sql`](./language-sql) | |
|
||||
| **language-text** | [`atom/language-text`](./language-text) | |
|
||||
| **language-todo** | [`atom/language-todo`](./language-todo) | |
|
||||
| **language-toml** | [`atom/language-toml`](./language-toml) | |
|
||||
| **language-typescript** | [`atom/language-typescript`](./language-typescript) | |
|
||||
| **language-xml** | [`atom/language-xml`](./language-xml) | |
|
||||
| **language-yaml** | [`atom/language-yaml`](./language-yaml) | |
|
||||
| **line-ending-selector** | [`./packages/line-ending-selector`](./line-ending-selector) | [#17847](https://github.com/atom/atom/issues/17847) |
|
||||
| **link** | [`./link`](./link) | [#17848](https://github.com/atom/atom/issues/17848) |
|
||||
| **markdown-preview** | [`atom/markdown-preview`][markdown-preview] | |
|
||||
| **language-sass** | [`./language-sass`](./language-sass) | |
|
||||
| **language-shellscript** | [`./language-shellscript`](./language-shellscript) | |
|
||||
| **language-source** | [`./language-source`](./language-source) | |
|
||||
| **language-sql** | [`./language-sql`](./language-sql) | |
|
||||
| **language-text** | [`./language-text`](./language-text) | |
|
||||
| **language-todo** | [`./language-todo`](./language-todo) | |
|
||||
| **language-toml** | [`./language-toml`](./language-toml) | |
|
||||
| **language-typescript** | [`./language-typescript`](./language-typescript) | |
|
||||
| **language-xml** | [`./language-xml`](./language-xml) | |
|
||||
| **language-yaml** | [`./language-yaml`](./language-yaml) | |
|
||||
| **line-ending-selector** | [`./line-ending-selector`](./line-ending-selector) | |
|
||||
| **link** | [`./link`](./link) | |
|
||||
| **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) | [#17853](https://github.com/atom/atom/issues/17853) |
|
||||
| **one-dark-ui** | [`./one-dark-ui`](./one-dark-ui) | [#17854](https://github.com/atom/atom/issues/17854) |
|
||||
| **one-light-syntax** | [`./one-light-syntax`](./one-light-syntax) | [#17855](https://github.com/atom/atom/issues/17855) |
|
||||
| **one-light-ui** | [`./one-light-ui`](./one-light-ui) | [#17856](https://github.com/atom/atom/issues/17856) |
|
||||
| **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] | |
|
||||
| **solarized-dark-syntax** | [`./solarized-dark-syntax`](./solarized-dark-syntax) | [#18280](https://github.com/atom/atom/issues/18280) |
|
||||
| **solarized-light-syntax** | [`./solarized-light-syntax`](./solarized-light-syntax) | [#18281](https://github.com/atom/atom/issues/18281) |
|
||||
| **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** | [`./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] | |
|
||||
| **update-package-dependencies** | [`./update-package-dependencies`](./update-package-dependencies) | [#18284](https://github.com/atom/atom/issues/18284) |
|
||||
| **welcome** | [`./welcome`](./welcome) | [#18285](https://github.com/atom/atom/issues/18285) |
|
||||
| **whitespace** | [`atom/whitespace`][whitespace] | |
|
||||
| **wrap-guide** | [`atom/wrap-guide`][wrap-guide] | [#18286](https://github.com/atom/atom/issues/18286) |
|
||||
| **status-bar** | [`./status-bar`](./status-bar) | |
|
||||
| **styleguide** | [`./styleguide`](./styleguide) | |
|
||||
| **symbols-view** | [`pulsar-edit/symbols-view`][symbols-view] | |
|
||||
| **tabs** | [`./tabs`](./tabs) | |
|
||||
| **timecop** | [`./timecop`](./timecop) | |
|
||||
| **tree-view** | [`pulsar-edit/tree-view`][tree-view] | |
|
||||
| **update-package-dependencies** | [`./update-package-dependencies`](./update-package-dependencies) | |
|
||||
| **welcome** | [`./welcome`](./welcome) | |
|
||||
| **whitespace** | [`./whitespace`](./whitespace) | |
|
||||
| **wrap-guide** | [`./wrap-guide`](./wrap-guide) | |
|
||||
|
||||
[archive-view]: https://github.com/atom/archive-view
|
||||
[autocomplete-atom-api]: https://github.com/atom/autocomplete-atom-api
|
||||
[autocomplete-css]: https://github.com/atom/autocomplete-css
|
||||
[autocomplete-html]: https://github.com/atom/autocomplete-html
|
||||
[autocomplete-plus]: https://github.com/atom/autocomplete-plus
|
||||
[autocomplete-snippets]: https://github.com/atom/autocomplete-snippets
|
||||
[autosave]: https://github.com/atom/autosave
|
||||
[background-tips]: https://github.com/atom/background-tips
|
||||
[bookmarks]: https://github.com/atom/bookmarks
|
||||
[bracket-matcher]: https://github.com/atom/bracket-matcher
|
||||
[command-palette]: https://github.com/atom/command-palette
|
||||
[encoding-selector]: https://github.com/atom/encoding-selector
|
||||
[find-and-replace]: https://github.com/atom/find-and-replace
|
||||
[fuzzy-finder]: https://github.com/atom/fuzzy-finder
|
||||
[github]: https://github.com/atom/github
|
||||
[image-view]: https://github.com/atom/image-view
|
||||
[keybinding-resolver]: https://github.com/atom/keybinding-resolver
|
||||
[language-c]: https://github.com/atom/language-c
|
||||
[language-clojure]: https://github.com/atom/language-clojure
|
||||
[language-coffee-script]: https://github.com/atom/language-coffee-script
|
||||
[language-csharp]: https://github.com/atom/language-csharp
|
||||
[language-css]: https://github.com/atom/language-css
|
||||
[language-gfm]: https://github.com/atom/language-gfm
|
||||
[language-git]: https://github.com/atom/language-git
|
||||
[language-go]: https://github.com/atom/language-go
|
||||
[language-html]: https://github.com/atom/language-html
|
||||
[language-hyperlink]: https://github.com/atom/language-hyperlink
|
||||
[language-java]: https://github.com/atom/language-java
|
||||
[language-javascript]: https://github.com/atom/language-javascript
|
||||
[language-json]: https://github.com/atom/language-json
|
||||
[language-less]: https://github.com/atom/language-less
|
||||
[language-make]: https://github.com/atom/language-make
|
||||
[language-mustache]: https://github.com/atom/language-mustache
|
||||
[language-objective-c]: https://github.com/atom/language-objective-c
|
||||
[language-perl]: https://github.com/atom/language-perl
|
||||
[language-php]: https://github.com/atom/language-php
|
||||
[language-property-list]: https://github.com/atom/language-property-list
|
||||
[language-python]: https://github.com/atom/language-python
|
||||
[language-ruby]: https://github.com/atom/language-ruby
|
||||
[language-ruby-on-rails]: https://github.com/atom/language-ruby-on-rails
|
||||
[language-sass]: https://github.com/atom/language-sass
|
||||
[language-shellscript]: https://github.com/atom/language-shellscript
|
||||
[language-source]: https://github.com/atom/language-source
|
||||
[language-sql]: https://github.com/atom/language-sql
|
||||
[language-text]: https://github.com/atom/language-text
|
||||
[language-todo]: https://github.com/atom/language-todo
|
||||
[language-toml]: https://github.com/atom/language-toml
|
||||
[language-typescript]: https://github.com/atom/language-typescript
|
||||
[language-xml]: https://github.com/atom/language-xml
|
||||
[language-yaml]: https://github.com/atom/language-yaml
|
||||
[markdown-preview]: https://github.com/atom/markdown-preview
|
||||
[notifications]: https://github.com/atom/notifications
|
||||
[open-on-github]: https://github.com/atom/open-on-github
|
||||
[package-generator]: https://github.com/atom/package-generator
|
||||
[settings-view]: https://github.com/atom/settings-view
|
||||
[snippets]: https://github.com/atom/snippets
|
||||
[spell-check]: https://github.com/atom/spell-check
|
||||
[status-bar]: https://github.com/atom/status-bar
|
||||
[styleguide]: https://github.com/atom/styleguide
|
||||
[symbols-view]: https://github.com/atom/symbols-view
|
||||
[tabs]: https://github.com/atom/tabs
|
||||
[timecop]: https://github.com/atom/timecop
|
||||
[tree-view]: https://github.com/atom/tree-view
|
||||
[whitespace]: https://github.com/atom/whitespace
|
||||
[wrap-guide]: https://github.com/atom/wrap-guide
|
||||
[autocomplete-atom-api]: https://github.com/pulsar-edit/autocomplete-atom-api
|
||||
[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
|
||||
[keybinding-resolver]: https://github.com/pulsar-edit/keybinding-resolver
|
||||
[notifications]: https://github.com/pulsar-edit/notifications
|
||||
[snippets]: https://github.com/pulsar-edit/snippets
|
||||
[spell-check]: https://github.com/pulsar-edit/spell-check
|
||||
[symbols-view]: https://github.com/pulsar-edit/symbols-view
|
||||
[tree-view]: https://github.com/pulsar-edit/tree-view
|
||||
|
@ -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 hackable text editor for the 21st Century.
|
||||
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.
|
||||
|
@ -31,7 +31,7 @@ module.exports = class AboutView extends EtchComponent {
|
||||
handleReleaseNotesClick(e) {
|
||||
e.preventDefault();
|
||||
shell.openExternal(
|
||||
this.props.updateManager.getReleaseNotesURLForAvailableVersion()
|
||||
this.props.updateManager.getReleaseNotesURLForAvailableVersion() //update-manager.js will need updating when we decide how to do the changelog
|
||||
);
|
||||
}
|
||||
|
||||
@ -45,13 +45,14 @@ module.exports = class AboutView extends EtchComponent {
|
||||
|
||||
handleTermsOfUseClick(e) {
|
||||
e.preventDefault();
|
||||
shell.openExternal('https://atom.io/terms');
|
||||
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) {
|
||||
e.preventDefault();
|
||||
shell.openExternal(
|
||||
'https://flight-manual.atom.io/getting-started/sections/installing-atom/'
|
||||
'https://pulsar-edit.dev/docs/launch-manual/sections/getting-started/#installing-pulsar'
|
||||
);
|
||||
}
|
||||
|
||||
@ -79,7 +80,7 @@ module.exports = class AboutView extends EtchComponent {
|
||||
$.header(
|
||||
{ className: 'about-header' },
|
||||
$.a(
|
||||
{ className: 'about-atom-io', href: 'https://atom.io' },
|
||||
{ className: 'about-atom-io', href: `${atom.branding.urlWeb}`, },
|
||||
$(AtomLogo)
|
||||
),
|
||||
$.div(
|
||||
@ -177,33 +178,26 @@ module.exports = class AboutView extends EtchComponent {
|
||||
},
|
||||
'License'
|
||||
),
|
||||
$.button(
|
||||
//Disabled the below as we don't have this but can reuse if there is the need
|
||||
/*$.button(
|
||||
{
|
||||
className: 'btn terms-of-use',
|
||||
onclick: this.handleTermsOfUseClick.bind(this)
|
||||
},
|
||||
'Terms of Use'
|
||||
)
|
||||
)*/
|
||||
)
|
||||
),
|
||||
|
||||
$.div(
|
||||
{ className: 'about-love group-start' },
|
||||
$.span({ className: 'icon icon-code' }),
|
||||
$.a({ className: 'icon icon-code', href: `${atom.branding.urlGH}` }),
|
||||
$.span({ className: 'inline' }, ' with '),
|
||||
$.span({ className: 'icon icon-heart' }),
|
||||
$.a({ className: 'icon icon-heart', href: `${atom.branding.urlWeb}` + "community" }),
|
||||
$.span({ className: 'inline' }, ' by '),
|
||||
$.a({ className: 'icon icon-logo-github', href: 'https://github.com' })
|
||||
//$.a({ className: 'icon icon-logo-github', href: `${atom.branding.urlWeb}` }) Replace icon with Pulsar word logo and delete following line
|
||||
$.a({ className: 'inline', href: `${atom.branding.urlWeb}` }, 'Pulsar Team')
|
||||
),
|
||||
|
||||
$.div(
|
||||
{ className: 'about-credits group-item' },
|
||||
$.span({ className: 'inline' }, 'And the awesome '),
|
||||
$.a(
|
||||
{ href: 'https://github.com/pulsar-edit/pulsar/contributors' },
|
||||
'Pulsar community'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
/** @babel */
|
||||
/** @jsx etch.dom */
|
||||
|
||||
const etch = require('etch');
|
||||
const EtchComponent = require('../etch-component');
|
||||
|
||||
@ -5,75 +8,29 @@ const $ = etch.dom;
|
||||
|
||||
module.exports = class AtomLogo extends EtchComponent {
|
||||
render() {
|
||||
return $.svg(
|
||||
{
|
||||
className: 'about-logo',
|
||||
width: '330px',
|
||||
height: '68px',
|
||||
viewBox: '0 0 330 68'
|
||||
},
|
||||
$.g(
|
||||
{
|
||||
stroke: 'none',
|
||||
'stroke-width': '1',
|
||||
fill: 'none',
|
||||
'fill-rule': 'evenodd'
|
||||
},
|
||||
$.g(
|
||||
{ transform: 'translate(2.000000, 1.000000)' },
|
||||
$.g(
|
||||
{
|
||||
transform: 'translate(96.000000, 8.000000)',
|
||||
fill: 'currentColor'
|
||||
},
|
||||
$.path({
|
||||
d:
|
||||
'M185.498,3.399 C185.498,2.417 186.34,1.573 187.324,1.573 L187.674,1.573 C188.447,1.573 189.01,1.995 189.5,2.628 L208.676,30.862 L227.852,2.628 C228.272,1.995 228.905,1.573 229.676,1.573 L230.028,1.573 C231.01,1.573 231.854,2.417 231.854,3.399 L231.854,49.403 C231.854,50.387 231.01,51.231 230.028,51.231 C229.044,51.231 228.202,50.387 228.202,49.403 L228.202,8.246 L210.151,34.515 C209.729,35.148 209.237,35.428 208.606,35.428 C207.973,35.428 207.481,35.148 207.061,34.515 L189.01,8.246 L189.01,49.475 C189.01,50.457 188.237,51.231 187.254,51.231 C186.27,51.231 185.498,50.458 185.498,49.475 L185.498,3.399 L185.498,3.399 Z'
|
||||
}),
|
||||
$.path({
|
||||
d:
|
||||
'M113.086,26.507 L113.086,26.367 C113.086,12.952 122.99,0.941 137.881,0.941 C152.77,0.941 162.533,12.811 162.533,26.225 L162.533,26.367 C162.533,39.782 152.629,51.792 137.74,51.792 C122.85,51.792 113.086,39.923 113.086,26.507 M158.74,26.507 L158.74,26.367 C158.74,14.216 149.89,4.242 137.74,4.242 C125.588,4.242 116.879,14.075 116.879,26.225 L116.879,26.367 C116.879,38.518 125.729,48.491 137.881,48.491 C150.031,48.491 158.74,38.658 158.74,26.507'
|
||||
}),
|
||||
$.path({
|
||||
d:
|
||||
'M76.705,5.155 L60.972,5.155 C60.06,5.155 59.287,4.384 59.287,3.469 C59.287,2.556 60.059,1.783 60.972,1.783 L96.092,1.783 C97.004,1.783 97.778,2.555 97.778,3.469 C97.778,4.383 97.005,5.155 96.092,5.155 L80.358,5.155 L80.358,49.405 C80.358,50.387 79.516,51.231 78.532,51.231 C77.55,51.231 76.706,50.387 76.706,49.405 L76.706,5.155 L76.705,5.155 Z'
|
||||
}),
|
||||
$.path({
|
||||
d:
|
||||
'M0.291,48.562 L21.291,3.05 C21.783,1.995 22.485,1.292 23.75,1.292 L23.891,1.292 C25.155,1.292 25.858,1.995 26.348,3.05 L47.279,48.421 C47.49,48.843 47.56,49.194 47.56,49.546 C47.56,50.458 46.788,51.231 45.803,51.231 C44.961,51.231 44.329,50.599 43.978,49.826 L38.219,37.183 L9.21,37.183 L3.45,49.897 C3.099,50.739 2.538,51.231 1.694,51.231 C0.781,51.231 0.008,50.529 0.008,49.685 C0.009,49.404 0.08,48.983 0.291,48.562 L0.291,48.562 Z M36.673,33.882 L23.749,5.437 L10.755,33.882 L36.673,33.882 L36.673,33.882 Z'
|
||||
})
|
||||
),
|
||||
$.g(
|
||||
{},
|
||||
$.path({
|
||||
d:
|
||||
'M40.363,32.075 C40.874,34.44 39.371,36.77 37.006,37.282 C34.641,37.793 32.311,36.29 31.799,33.925 C31.289,31.56 32.791,29.23 35.156,28.718 C37.521,28.207 39.851,29.71 40.363,32.075',
|
||||
fill: 'currentColor'
|
||||
}),
|
||||
$.path({
|
||||
d:
|
||||
'M48.578,28.615 C56.851,45.587 58.558,61.581 52.288,64.778 C45.822,68.076 33.326,56.521 24.375,38.969 C15.424,21.418 13.409,4.518 19.874,1.221 C22.689,-0.216 26.648,1.166 30.959,4.629',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '3.08',
|
||||
'stroke-linecap': 'round'
|
||||
}),
|
||||
$.path({
|
||||
d:
|
||||
'M7.64,39.45 C2.806,36.94 -0.009,33.915 0.154,30.79 C0.531,23.542 16.787,18.497 36.462,19.52 C56.137,20.544 71.781,27.249 71.404,34.497 C71.241,37.622 68.127,40.338 63.06,42.333',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '3.08',
|
||||
'stroke-linecap': 'round'
|
||||
}),
|
||||
$.path({
|
||||
d:
|
||||
'M28.828,59.354 C23.545,63.168 18.843,64.561 15.902,62.653 C9.814,58.702 13.572,42.102 24.296,25.575 C35.02,9.048 48.649,-1.149 54.736,2.803 C57.566,4.639 58.269,9.208 57.133,15.232',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '3.08',
|
||||
'stroke-linecap': 'round'
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
return (
|
||||
<svg className='about-logo' xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 570.40002 191.69999" width="570.40002" height="100">
|
||||
<defs id="defs400"></defs>
|
||||
<path
|
||||
fill="currentColor"
|
||||
id="path42"
|
||||
d="m 95.9,72.6 c -12.8,0 -23.2,10.4 -23.2,23.2 0,12.8 10.4,23.2 23.2,23.2 12.8,0 23.2,-10.4 23.2,-23.2 0,-12.8 -10.4,-23.2 -23.2,-23.2 z"
|
||||
class="st0" />
|
||||
<path fill="currentColor" id="path44" d="m 67.4,127.7 c 0.8,0.3 1.6,0.5 2.4,0.5 1.6,0 3.1,-0.6 4.3,-1.8 2.4,-2.4 2.4,-6.3 0,-8.7 -1.2,-1.2 -2.8,-1.8 -4.4,-1.8 -1.6,0 -3.2,0.6 -4.4,1.8 -1.8,1.8 -2.3,4.5 -1.3,6.7 l -12.4,4.8 -51.6,61.4 1.1,1.1 61.4,-51.6 z" class="st0" />
|
||||
<path fill="currentColor" id="path46" d="m 58,152.1 c 5.4,4.6 10.9,8.7 16.7,12.4 2.1,-0.8 6.7,-2.6 8.7,-3.8 -7.1,-4.1 -12.8,-8.3 -19.3,-13.8 z" class="st0" />
|
||||
<path fill="currentColor" id="path48" d="M 129.2,51.6 124.4,64 c -0.8,-0.3 -1.6,-0.5 -2.3,-0.5 -1.6,0 -3.1,0.6 -4.3,1.8 -2.4,2.4 -2.4,6.3 0,8.7 1.2,1.2 2.8,1.8 4.4,1.8 1.6,0 3.2,-0.6 4.4,-1.8 1.8,-1.8 2.3,-4.5 1.3,-6.7 L 140.3,62.5 191.9,1.1 190.8,0 Z" class="st0" />
|
||||
<path fill="currentColor" id="path50" d="m 121.3,54.8 c -7.4,-4.6 -16.1,-7.3 -25.4,-7.3 -26.6,0 -48.3,21.7 -48.3,48.3 0,9.3 2.7,18 7.3,25.4 l 2.6,-1 c 0.4,-2.6 1.6,-5 3.5,-7 0.4,-0.4 0.8,-0.7 1.3,-1.1 -2.4,-4.9 -3.8,-10.5 -3.8,-16.3 0,-20.6 16.8,-37.4 37.4,-37.4 5.9,0 11.4,1.4 16.3,3.8 0.3,-0.4 0.6,-0.9 1,-1.3 1.9,-1.9 4.3,-3.1 7,-3.5 z" class="st0" />
|
||||
<path fill="currentColor" id="path52" d="m 95.9,133.2 c -5.9,0 -11.4,-1.4 -16.3,-3.8 -0.3,0.4 -0.6,0.9 -1,1.3 -1.9,1.9 -4.3,3.1 -7,3.5 l -1,2.6 c 7.4,4.6 16.1,7.3 25.4,7.3 26.6,0 48.3,-21.7 48.3,-48.3 0,-9.3 -2.7,-18 -7.3,-25.4 l -2.6,1 c -0.4,2.6 -1.6,5 -3.5,7 -0.4,0.4 -0.8,0.7 -1.3,1.1 2.4,4.9 3.8,10.5 3.8,16.3 -0.1,20.7 -16.9,37.4 -37.5,37.4 z" class="st0" />
|
||||
<path fill="currentColor" id="path54" d="m 16.2,95.9 c -10,24.6 -10.5,48.8 0.1,65.7 l 5.3,-6.3 c -7.2,-13.1 -7.2,-30.8 -0.9,-49.5 5,9.7 11.4,19.2 19,28 l 5.1,-6 C 36.3,117.7 29.5,106.9 24.6,95.9 31,81.5 40.9,67 54,53.9 66.8,41.1 81.2,31.1 95.9,24.5 c 10.8,4.8 21.7,11.5 32,20.2 l 6,-5.1 c -9,-7.7 -18.6,-14 -28.1,-18.9 3.2,-1.1 6.3,-2 9.4,-2.7 15.8,-3.6 29.6,-2.3 40.2,3.5 l 6.3,-5.3 C 149.2,8.2 132.4,6.1 113.5,10.4 107.6,11.7 101.7,13.6 95.8,16.1 67.2,4.4 39.2,5.7 22.5,22.4 9.6,35.3 5.3,55.2 10.5,78.3 c 1.3,5.9 3.3,11.8 5.7,17.6 z m 11.7,-68 C 41.1,14.7 62.8,12.8 86,20.6 72.8,27.4 59.9,36.8 48.4,48.4 36.7,60.1 27.4,73 20.7,86 19.7,82.9 18.7,79.8 18,76.6 13.5,56.1 17,38.8 27.9,27.9 Z" class="st0" />
|
||||
<path fill="currentColor" id="path56" d="m 147.1,63.9 c 8.6,10.3 15.4,21.2 20.2,31.9 l -0.1,0.3 c -6.6,14.7 -16.7,29.1 -29.2,41.6 -18.4,18.4 -40.1,31.1 -61.2,35.9 -15.8,3.6 -29.6,2.3 -40.2,-3.5 l -6.3,5.3 c 8.3,5.3 18.4,8 29.7,8 5.9,0 12.1,-0.7 18.5,-2.2 22.5,-5.1 45.6,-18.5 65,-37.9 11.4,-11.4 20.9,-24.3 27.8,-37.6 7.8,23.2 5.9,44.9 -7.3,58.1 -10,10 -25.7,13.7 -43.8,10.8 -3.4,2.1 -6.8,4 -10.3,5.7 7.7,2 15.1,3.1 22,3.1 15.2,0 28.3,-4.8 37.6,-14.1 C 193.7,145.1 185.6,97 152.3,57.9 Z" class="st0" />
|
||||
<path fill="currentColor" id="path58" d="m 170.2,36.4 c 4.4,8.1 6.1,18.2 5.1,29.5 2.3,3.6 4.4,7.3 6.2,10.9 3.8,-18.3 1.7,-34.5 -6.1,-46.8 z" class="st0" />
|
||||
<path fill="currentColor" id="path60" d="m 263.9,70.6 h -41.6 v 56.7 h 9.7 v -19.7 h 0.7 l 31.1,-0.1 c 3,0 5.5,-1.1 7.6,-3.2 2.1,-2.1 3.2,-4.6 3.2,-7.5 V 81.3 c 0,-2.9 -1.1,-5.5 -3.2,-7.5 -2,-2.1 -4.6,-3.2 -7.5,-3.2 z m 1,26.3 c 0,0.6 -0.4,1 -1,1 h -30.8 c -0.6,0 -1,-0.4 -1,-1 V 81.4 c 0,-0.6 0.4,-1 1,-1 h 30.8 c 0.6,0 1,0.4 1,1 z" class="st0" />
|
||||
<path fill="currentColor" id="path62" d="m 324.5,116.7 c 0,0.7 -0.5,1 -0.9,1 h -30.9 c -0.6,0 -1,-0.4 -1,-1 V 70.6 H 282 v 46.1 c 0,3 1,5.5 3.1,7.6 2.1,2.1 4.6,3.1 7.6,3.1 h 30.9 c 2.9,0 5.5,-1.1 7.5,-3.1 2.1,-2.1 3.2,-4.6 3.2,-7.6 V 70.6 h -9.8 z" class="st0" />
|
||||
<polygon transform="translate(697.6,5098.3)" fill="currentColor" id="polygon64" points="-353.6,-4970.9 -307.4,-4970.9 -307.4,-4980.7 -343.8,-4980.7 -343.8,-5027.8 -353.6,-5027.8 " class="st0" />
|
||||
<path fill="currentColor" id="path66" d="m 436.4,70.5 h -30.9 c -3,0 -5.5,1.1 -7.6,3.1 -2.1,2.1 -3.1,4.6 -3.1,7.6 v 11.9 c 0,3 1,5.5 3.1,7.6 2.1,2.1 4.6,3.1 7.6,3.1 h 30.9 c 0.4,0 0.9,0.3 0.9,1 v 11.9 c 0,0.7 -0.5,1 -0.9,1 h -30.9 c -0.6,0 -1,-0.4 -1,-1 v -4 h -9.7 v 4 c 0,3 1,5.5 3.1,7.6 2.1,2.1 4.6,3.1 7.6,3.1 h 30.9 c 2.9,0 5.5,-1.1 7.5,-3.1 2.1,-2.1 3.2,-4.6 3.2,-7.6 v -11.9 c 0,-3 -1.1,-5.5 -3.2,-7.6 -2.1,-2.1 -4.6,-3.1 -7.5,-3.1 h -30.9 c -0.6,0 -1,-0.4 -1,-1 V 81.2 c 0,-0.6 0.4,-1 1,-1 h 30.9 c 0.4,0 0.9,0.3 0.9,1 v 4 h 9.8 v -4 c 0,-3 -1.1,-5.5 -3.2,-7.6 -2,-2 -4.6,-3.1 -7.5,-3.1 z" class="st0" />
|
||||
<path fill="currentColor" id="path68" d="m 498.3,70.5 h -30.8 c -3,0 -5.5,1.1 -7.6,3.1 -2.1,2.1 -3.1,4.6 -3.1,7.6 v 46.1 h 9.7 v -19.4 h 32.8 v 19.4 h 9.8 V 81.2 c 0,-3 -1.1,-5.5 -3.2,-7.6 -2.1,-2 -4.7,-3.1 -7.6,-3.1 z m 1,27.8 h -32.8 v -17 c 0,-0.6 0.4,-1 1,-1 h 30.8 c 0.6,0 1,0.4 1,1 z" class="st0" />
|
||||
<path fill="currentColor" id="path70" d="m 567.2,104.4 c 2.1,-2.1 3.2,-4.6 3.2,-7.5 V 81.4 c 0,-2.9 -1.1,-5.5 -3.2,-7.5 -2.1,-2.1 -4.7,-3.2 -7.6,-3.2 h -41.5 v 56.7 h 9.7 v -19.8 h 15 l 0.1,0.2 16.5,19.6 h 10.9 v -2.1 l -14.8,-17.6 h 4 c 3.1,-0.1 5.6,-1.2 7.7,-3.3 z m -38.4,-6.5 c -0.6,0 -1,-0.4 -1,-1 V 81.4 c 0,-0.6 0.4,-1 1,-1 h 30.8 c 0.6,0 1,0.4 1,1 v 15.5 c 0,0.6 -0.4,1 -1,1 z" class="st0" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
};
|
||||
|
@ -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')) {
|
||||
|
1819
packages/about/package-lock.json
generated
1819
packages/about/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,21 +4,14 @@
|
||||
"main": "./lib/main",
|
||||
"version": "1.9.1",
|
||||
"description": "View useful information about your Pulsar installation.",
|
||||
"keywords": [],
|
||||
"repository": "https://github.com/pulsar-edit/pulsar",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"lint": "standard"
|
||||
},
|
||||
"engines": {
|
||||
"atom": ">=1.7 <2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"etch": "0.9.0",
|
||||
"semver": "^5.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"standard": "^11.0.0"
|
||||
"etch": "^0.14.1",
|
||||
"semver": "^7.3.8"
|
||||
},
|
||||
"consumedServices": {
|
||||
"status-bar": {
|
||||
@ -29,16 +22,5 @@
|
||||
},
|
||||
"deserializers": {
|
||||
"AboutView": "deserializeAboutView"
|
||||
},
|
||||
"standard": {
|
||||
"env": [
|
||||
"browser",
|
||||
"node",
|
||||
"atomtest",
|
||||
"jasmine"
|
||||
],
|
||||
"globals": [
|
||||
"atom"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -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('Atom 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('Atom 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,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,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
|
10
packages/autocomplete-css/README.md
Normal file
10
packages/autocomplete-css/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# 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 completions by running `node update.js` at the root of this package and checking for changes within `completions.json`. This does rely on having dev dependencies installed, so ensure you install all dependencies before doing so.
|
7581
packages/autocomplete-css/completions.json
Normal file
7581
packages/autocomplete-css/completions.json
Normal file
File diff suppressed because it is too large
Load Diff
163
packages/autocomplete-css/cssValueDefinitionSyntaxExtractor.js
Normal file
163
packages/autocomplete-css/cssValueDefinitionSyntaxExtractor.js
Normal file
@ -0,0 +1,163 @@
|
||||
// Due to the complexity of CSS Value Definition Syntax
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/Value_definition_syntax
|
||||
// We will go ahead and create a small parser for handling it.
|
||||
// This parser is only intended to receive some syntax, and spit out an array
|
||||
// of all valid value identifiers within it. Ignoring all special conventions of
|
||||
// the syntax.
|
||||
|
||||
class CSSParser {
|
||||
constructor(input) {
|
||||
this.index = 0;
|
||||
this.value = input;
|
||||
this.out = [];
|
||||
|
||||
// Manage States
|
||||
this.buffer = ""; // Used to store uncomplete values while looping.
|
||||
|
||||
// Definitions
|
||||
this.keywords = {
|
||||
"*": "Asterisk Multiplier",
|
||||
"+": "Plus Sign Multiplier",
|
||||
"?": "Question Mark Multiplier",
|
||||
"#": "Hash Mark Multiplier",
|
||||
"!": "Exclamation Point Multiplier"
|
||||
};
|
||||
|
||||
this.separators = {
|
||||
"&&": "Double Ampersand Combinator",
|
||||
"||": "Double Bar Combinator",
|
||||
"|": "Single Bar Combinator",
|
||||
"[": "Open Bracket Combinator",
|
||||
"]": "Close Bracket Combinator",
|
||||
" ": "Juxtaposition Combinator",
|
||||
"/": "Undocumented Seperator?"
|
||||
};
|
||||
|
||||
this.startFold = "<"; // A foldable item would mean to stop parsing within.
|
||||
this.endFold = ">";
|
||||
this.startDiscardable = "{";
|
||||
this.endDiscardable = "}";
|
||||
}
|
||||
|
||||
parse() {
|
||||
let cur = this.cur();
|
||||
|
||||
if (this.index === this.value.length || this.index > this.value.length) {
|
||||
// We have hit the end of our index. Lets return
|
||||
this.offLoadBuffer();
|
||||
return this.out;
|
||||
}
|
||||
|
||||
if (this.isStartDiscardable()) {
|
||||
// We don't care about what's in here, until we hit the end of our discardable
|
||||
this.offLoadBuffer();
|
||||
while(!this.isEndDiscardable()) {
|
||||
this.next();
|
||||
}
|
||||
this.next();
|
||||
return this.parse();
|
||||
}
|
||||
|
||||
if (this.isKeyword().status) {
|
||||
// We don't actually care about keywords.
|
||||
this.offLoadBuffer();
|
||||
this.next(this.isKeyword().who.length);
|
||||
return this.parse();
|
||||
}
|
||||
|
||||
if (this.isSeparators().status) {
|
||||
// We don't actually care about seperators
|
||||
this.offLoadBuffer();
|
||||
this.next(this.isSeparators().who.length);
|
||||
return this.parse();
|
||||
}
|
||||
|
||||
if (this.isStartFold()) {
|
||||
let tmpValue = "";
|
||||
while(!this.isEndFold()) {
|
||||
tmpValue += this.cur();
|
||||
this.next();
|
||||
}
|
||||
tmpValue += this.cur();
|
||||
this.out.push(tmpValue);
|
||||
this.next();
|
||||
return this.parse();
|
||||
}
|
||||
|
||||
if (!this.isStartDiscardable() && !this.isEndDiscardable() && !this.isKeyword().status && !this.isSeparators().status && !this.isStartFold() && !this.isEndFold()) {
|
||||
this.buffer += this.cur();
|
||||
this.next();
|
||||
return this.parse();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
offLoadBuffer() {
|
||||
if (this.buffer.length > 0) {
|
||||
this.out.push(this.buffer);
|
||||
this.buffer = "";
|
||||
}
|
||||
}
|
||||
|
||||
isKeyword() {
|
||||
for (const name in this.keywords) {
|
||||
if (this.keywords.hasOwnProperty(name) && this.value.substr(this.index, name.length) === name) {
|
||||
return { status: true, who: name };
|
||||
}
|
||||
}
|
||||
return { status: false };
|
||||
}
|
||||
|
||||
isSeparators() {
|
||||
for (const name in this.separators) {
|
||||
if (this.separators.hasOwnProperty(name) && this.value.substr(this.index, name.length) === name) {
|
||||
return { status: true, who: name };
|
||||
}
|
||||
}
|
||||
return { status: false };
|
||||
}
|
||||
|
||||
isStartFold() {
|
||||
if (this.cur() === this.startFold) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
isEndFold() {
|
||||
if (this.cur() === this.endFold) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
isStartDiscardable() {
|
||||
if (this.cur() === this.startDiscardable) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
isEndDiscardable() {
|
||||
if (this.cur() === this.endDiscardable) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cur() {
|
||||
return this.value.charAt(this.index);
|
||||
}
|
||||
|
||||
next(amount) {
|
||||
let increase = amount ?? 1;
|
||||
this.index = this.index + increase;
|
||||
return this.value.charAt(this.index);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CSSParser;
|
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()
|
898
packages/autocomplete-css/manual-property-desc.json
Normal file
898
packages/autocomplete-css/manual-property-desc.json
Normal file
@ -0,0 +1,898 @@
|
||||
{
|
||||
"-webkit-align-items": {
|
||||
"desc": "Legacy Alias of align-items.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-align-content": {
|
||||
"desc": "Legacy Alias of align-content.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-align-self": {
|
||||
"desc": "Legacy Alias of align-self.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-animation-name": {
|
||||
"desc": "Legacy Alias of animation-name.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-animation-duration": {
|
||||
"desc": "Legacy Alias of animation-duration.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-animation-timing-function": {
|
||||
"desc": "Legacy Alias of animation-timing-function.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-animation-iteration-count": {
|
||||
"desc": "Legacy Alias of animation-iteration-count.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-animation-direction": {
|
||||
"desc": "Legacy Alias of animation-direction.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-animation-play-state": {
|
||||
"desc": "Legacy Alias of animation-play-state.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-animation-delay": {
|
||||
"desc": "Legacy Alias of animation-delay.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-animation-fill-mode": {
|
||||
"desc": "Legacy Alias of animation-fill-mode.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-animation": {
|
||||
"desc": "Legacy Alias of animation.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-backface-visibility": {
|
||||
"desc": "Legacy Alias of backface-visibility.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-background-clip": {
|
||||
"desc": "Legacy Alias of background-clip.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-background-origin": {
|
||||
"desc": "Legacy Alias of background-origin.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-background-size": {
|
||||
"desc": "Improper implementation of a legacy alias for background-size.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-border-bottom-left-radius": {
|
||||
"desc": "Legacy Alias of border-bottom-left-radius.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-border-bottom-right-radius": {
|
||||
"desc": "Legacy Alias of border-bottom-right-radius.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-border-top-left-radius": {
|
||||
"desc": "Legacy Alias of border-top-left-radius.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-border-top-right-radius": {
|
||||
"desc": "Legacy Alias of border-top-right-radius.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-border-radius": {
|
||||
"desc": "Legacy Alias of border-radius.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-box-shadow": {
|
||||
"desc": "Legacy Alias of box-shadow.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-box-sizing": {
|
||||
"desc": "Legacy Alias of box-sizing.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-flex": {
|
||||
"desc": "Legacy Alias of flex.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-flex-basis": {
|
||||
"desc": "Legacy Alias of flex-basis.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-flex-direction": {
|
||||
"desc": "Legacy Alias of flex-direction.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-flex-flow": {
|
||||
"desc": "Legacy Alias of flex-flow.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-flex-grow": {
|
||||
"desc": "Legacy Alias of flex-grow.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-flex-shrink": {
|
||||
"desc": "Legacy Alias of flex-shrink.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-flex-wrap": {
|
||||
"desc": "Legacy Alias of flex-wrap.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-filter": {
|
||||
"desc": "Legacy Alias of filter.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-justify-content": {
|
||||
"desc": "Legacy Alias of justify-content.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask": {
|
||||
"desc": "Legacy Alias of mask.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-box-image-outset": {
|
||||
"desc": "Legacy Alias of mask-border-outset.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-box-image-repeat": {
|
||||
"desc": "Legacy Alias of mask-border-repeat.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-box-image-slice": {
|
||||
"desc": "Legacy Alias of mask-border-slice.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-box-image-source": {
|
||||
"desc": "Legacy Alias of mask-border-source.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-box-image-width": {
|
||||
"desc": "Legacy Alias of mask-border-width.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-clip": {
|
||||
"desc": "Legacy Alias of mask-clip.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-image": {
|
||||
"desc": "Legacy Alias of mask-image.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-origin": {
|
||||
"desc": "Legacy Alias of mask-origin.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-position": {
|
||||
"desc": "Legacy Alias of mask-position.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-repeat": {
|
||||
"desc": "Legacy Alias of mask-repeat.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-mask-size": {
|
||||
"desc": "Legacy Alias of mask-size.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-order": {
|
||||
"desc": "Legacy Alias of order.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-perspective": {
|
||||
"desc": "Legacy Alias of perspective.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-perspective-origin": {
|
||||
"desc": "Legacy Alias of perspective-origin.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-transform-origin": {
|
||||
"desc": "Legacy Alias of transform-origin.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-transform-style": {
|
||||
"desc": "Legacy Alias of transform-style.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-transform": {
|
||||
"desc": "Legacy Alias of transform.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-transition-delay": {
|
||||
"desc": "Legacy Alias of transition-delay.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-transition-duration": {
|
||||
"desc": "Legacy Alias of transition-duration.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-transition-property": {
|
||||
"desc": "Legacy Alias of transition-property.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-transition-timing-function": {
|
||||
"desc": "Legacy Alias of transition-timing-function.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-transition": {
|
||||
"desc": "Legacy Alias of transition.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-simple-aliases"
|
||||
},
|
||||
"-webkit-appearance": {
|
||||
"desc": "Legacy Name Alias of appearance.",
|
||||
"spec": "https://drafts.csswg.org/css-ui/#appearance-switching"
|
||||
},
|
||||
"-webkit-user-select": {
|
||||
"desc": "Alias shorthand property of user-select.",
|
||||
"spec": "https://drafts.csswg.org/css-ui/#propdef--webkit-user-select"
|
||||
},
|
||||
"-webkit-text-size-adjust": {
|
||||
"desc": "Vendor Prefixed Legacy Name Alias. (-vendorPrefix-)text-size-adjust",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-prefixed-aliases"
|
||||
},
|
||||
"-webkit-box-align": {
|
||||
"desc": "Vendor prefixed property mapping to align-items.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-property-mappings"
|
||||
},
|
||||
"-webkit-box-flex": {
|
||||
"desc": "Vendor prefixed property mapping to flex-grow.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-property-mappings"
|
||||
},
|
||||
"-webkit-box-ordinal-group": {
|
||||
"desc": "Vendor prefixed property mapping to order.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-property-mappings"
|
||||
},
|
||||
"-webkit-box-orient": {
|
||||
"desc": "Vendor prefixed property mapping to flex-direction.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-property-mappings"
|
||||
},
|
||||
"-webkit-box-pack": {
|
||||
"desc": "Vendor prefixed property mapping to justify-content.",
|
||||
"spec": "https://compat.spec.whatwg.org/#css-property-mappings"
|
||||
},
|
||||
"fill-break": {
|
||||
"desc": "This property specifies how the geometry of a fragmented box is treated for fills.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#fill-break"
|
||||
},
|
||||
"fill-image": {
|
||||
"desc": "This property sets the fill images of an element. Images are drawn with the first specified one on top (closest to the user) and each subsequent image behind the previous one.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#fill-image"
|
||||
},
|
||||
"fill-origin": {
|
||||
"desc": "This property specifies the coordinate system of the fill, setting the fill positioning area.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#fill-origin"
|
||||
},
|
||||
"fill-position": {
|
||||
"desc": "If fill images have been specified, this property specifies their initial position (after any resizing) within their corresponding fill positioning area.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#fill-position"
|
||||
},
|
||||
"fill-size": {
|
||||
"desc": "Specifies the size of the fill images. Values are interpreted identically to background-size, mutatis mutandi.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#fill-size"
|
||||
},
|
||||
"fill-repeat": {
|
||||
"desc": "Specifies how fill images are tiled after they have been sized and positioned.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#fill-repeat"
|
||||
},
|
||||
"stroke-align": {
|
||||
"desc": "This property allows the author to align a stroke along the outline.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#stroke-align"
|
||||
},
|
||||
"stroke-break": {
|
||||
"desc": "This property specifies how the geometry of a fragmented box is treated for strokes.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#stroke-break"
|
||||
},
|
||||
"stroke-dash-corner": {
|
||||
"desc": "The stroke-dash-corner property controls whether a dash is always painted at the vertices of a stroked shape.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#propdef-stroke-dash-corner"
|
||||
},
|
||||
"stroke-dash-justify": {
|
||||
"desc": "The stroke-dash-justify property specifies whether and how a stroke's dash pattern will be adjusted so that it is repeated a whole number of times along each of an element's subpaths.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#propdef-stroke-dash-justify"
|
||||
},
|
||||
"stroke-color": {
|
||||
"desc": "This property sets the stroke colors of an element.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#stroke-color"
|
||||
},
|
||||
"stroke-image": {
|
||||
"desc": "This property sets the stroke images of an element.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#stroke-image"
|
||||
},
|
||||
"stroke-origin": {
|
||||
"desc": "This property specifies the coordinate system of the stroke, setting the stroke positioning area.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#stroke-origin"
|
||||
},
|
||||
"stroke-position": {
|
||||
"desc": "If stroke images have been specified, this property specifies their initial position (after any resizing) within their corresponding stroke positioning area.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#stroke-position"
|
||||
},
|
||||
"stroke-size": {
|
||||
"desc": "Specifies the size of the stroke images.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#stroke-size"
|
||||
},
|
||||
"stroke-repeat": {
|
||||
"desc": "Specifies how stroke fill images are tiled after they have been sized and positioned.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#stroke-repeat"
|
||||
},
|
||||
"shape-subtract": {
|
||||
"desc": "The shape-subtract property allows one to exclude part of the content area from the wrapping area. The excluded area is the addition of all the areas defined in a list of CSS basic shapes and/or SVG shapes.",
|
||||
"spec": "https://svgwg.org/svg2-draft/text.html#TextShapeSubtract"
|
||||
},
|
||||
"stroke-alignment": {
|
||||
"desc": "This property allows the author to align a stroke along the outline of the current object.",
|
||||
"spec": "https://svgwg.org/specs/strokes/#SpecifyingStrokeAlignment"
|
||||
},
|
||||
"stroke-dashcorner": {
|
||||
"desc": "The stroke-dashcorner property controls whether a dash is always painted at the vertices of a stroked shape.",
|
||||
"spec": "https://svgwg.org/specs/strokes/#StrokeDashcornerProperty"
|
||||
},
|
||||
"stroke-dashadjust": {
|
||||
"desc": "The stroke-dashadjust property specifies whether and how a stroke's dash pattern will be adjusted so that it is repeated a whole number of times along an element's subpaths.",
|
||||
"spec": "https://svgwg.org/specs/strokes/#StrokeDashadjustProperty"
|
||||
},
|
||||
"grid-row-gap": {
|
||||
"desc": "Shorthand for the row-gap property.",
|
||||
"spec": "https://drafts.csswg.org/css-align-3/#gap-legacy"
|
||||
},
|
||||
"grid-column-gap": {
|
||||
"desc": "Shorthand for the column-gap property.",
|
||||
"spec": "https://drafts.csswg.org/css-align-3/#gap-legacy"
|
||||
},
|
||||
"grid-gap": {
|
||||
"desc": "Shorthand for the gap property.",
|
||||
"spec": "https://drafts.csswg.org/css-align-3/#gap-legacy"
|
||||
},
|
||||
"anchor-scroll": {
|
||||
"desc": "The anchor-scroll property allows an author to compensate for none aligned positioned elements and their anchor without losing the performance benefits of the separate scrolling thread.",
|
||||
"spec": "https://drafts.csswg.org/css-anchor-position-1/#scroll"
|
||||
},
|
||||
"anchor-name": {
|
||||
"desc": "Allows anchor functions to refer to an anchor element by name.",
|
||||
"spec": "https://drafts.csswg.org/css-anchor-position-1/#determining"
|
||||
},
|
||||
"anchor-default": {
|
||||
"desc": "The anchor-default property defines the default anchor specifier for all anchor functions on the element.",
|
||||
"spec": "https://drafts.csswg.org/css-anchor-position-1/#anchor-default"
|
||||
},
|
||||
"position-fallback": {
|
||||
"desc": "Provides blocks of style rules to try out. The first that doesn't cause the element to overflow its containing block is taken as the winner.",
|
||||
"spec": "https://drafts.csswg.org/css-anchor-position-1/#fallback-property"
|
||||
},
|
||||
"background-position-inline": {
|
||||
"desc": "This property specifies the background position's inline-axis component.",
|
||||
"spec": "https://drafts.csswg.org/css-backgrounds-4/#background-position-longhands"
|
||||
},
|
||||
"background-position-block": {
|
||||
"desc": "This property specifies the background position's block-axis component.",
|
||||
"spec": "https://drafts.csswg.org/css-backgrounds-4/#propdef-background-position-block"
|
||||
},
|
||||
"corner-shape": {
|
||||
"desc": "The corner-shape property specifies a reinterpretation of the radii to define other corner shapes.",
|
||||
"spec": "https://drafts.csswg.org/css-backgrounds-4/#corner-shaping"
|
||||
},
|
||||
"corners": {
|
||||
"desc": "The corners shorthand sets corner-shape and border-radius in the same declaration.",
|
||||
"spec": "https://drafts.csswg.org/css-backgrounds-4/#corners-shorthand"
|
||||
},
|
||||
"border-limit": {
|
||||
"desc": "Specifies which part of the border is rendered.",
|
||||
"spec": "https://drafts.csswg.org/css-backgrounds-4/#border-limit"
|
||||
},
|
||||
"border-clip": {
|
||||
"desc": "Shorthand for border-clip-top, border-clip-right, border-clip-bottom, and border-clip-left.",
|
||||
"spec": "https://drafts.csswg.org/css-backgrounds-4/#border-clip"
|
||||
},
|
||||
"border-clip-top": {
|
||||
"desc": "Splits the top border into parts along the border edge.",
|
||||
"spec": "https://drafts.csswg.org/css-backgrounds-4/#border-clip"
|
||||
},
|
||||
"border-clip-right": {
|
||||
"desc": "Splits the right border into parts along the border edge.",
|
||||
"spec": "https://drafts.csswg.org/css-backgrounds-4/#border-clip"
|
||||
},
|
||||
"border-clip-bottom": {
|
||||
"desc": "Splits the bottom border into parts along the border edge.",
|
||||
"spec": "https://drafts.csswg.org/css-backgrounds-4/#border-clip"
|
||||
},
|
||||
"border-clip-left": {
|
||||
"desc": "Splits the left border into parts along the border edge.",
|
||||
"spec": "https://drafts.csswg.org/css-backgrounds-4/#border-clip"
|
||||
},
|
||||
"voice-family": {
|
||||
"desc": "The voice-family property specifies a prioritized list of component values that are separated by commas to indicate that they are alternatives.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#voice-props-voice-family"
|
||||
},
|
||||
"voice-rate": {
|
||||
"desc": "The voice-rate property manipulates the rate of generated synthetic speech in terms of words per minute.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#voice-props-voice-rate"
|
||||
},
|
||||
"voice-pitch": {
|
||||
"desc": "The voice-pitch property specifies the 'baseline' pitch of the generated speech output, which depends on the user 'voice-family' instance, and varies across speech synthesis processors.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#voice-props-voice-pitch"
|
||||
},
|
||||
"voice-range": {
|
||||
"desc": "The voice-range property specifies the variability in the 'baseline' pitch.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#voice-props-voice-range"
|
||||
},
|
||||
"voice-stress": {
|
||||
"desc": "The voice-stress property manipulates the strength of emphasis, which is normally applied using a combination of pitch change, timing changes, loudness and other acoustic differences.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#voice-props-voice-stress"
|
||||
},
|
||||
"voice-duration": {
|
||||
"desc": "The voice-duration property specifies how long it should take to render the selected element's content.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#mixing-props-voice-duration"
|
||||
},
|
||||
"voice-volume": {
|
||||
"desc": "The voice-volume property allows authors to control the amplitude of the audio waveform generated by the speech synthesizer, and is also used to adjust the relative volume level of audio cues within the aural box model of the selected element.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#mixing-props-voice-volume"
|
||||
},
|
||||
"voice-balance": {
|
||||
"desc": "The voice-balance property controls the spatial distribution of audio output across a lateral sound stage: one extremity is on the left, the other extremity is on the right hand side, relative to the listener’s position.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#mixing-props-voice-balance"
|
||||
},
|
||||
"speak": {
|
||||
"desc": "The speak property determines whether or not to render text aurally.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#speaking-props-speak"
|
||||
},
|
||||
"speak-as": {
|
||||
"desc": "The speak-as property determines in what manner text gets rendered aurally, based upon a predefined list of possibilities.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#speaking-props-speak-as"
|
||||
},
|
||||
"pause-before": {
|
||||
"desc": "The pause-before property specifies a prosodic boundary (silence with a specific duration) that occurs before the speech synthesis rendition of the element.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#pause-props-pause-before-after"
|
||||
},
|
||||
"pause-after": {
|
||||
"desc": "The pause-after property specifies a prosodic boundary (silence with a specific duration) that occurs after the speech synthesis rendition of the element.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#pause-props-pause-before-after"
|
||||
},
|
||||
"pause": {
|
||||
"desc": "The pause property is a shorthand property for pause-before and pause-after.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#pause-props-pause"
|
||||
},
|
||||
"rest-before": {
|
||||
"desc": "The rest-before property specifies a prosodic boundary (silence with a specific duration) that occurs before the speech synthesis rendition of an element.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#rest-props-rest-before-after"
|
||||
},
|
||||
"rest-after": {
|
||||
"desc": "The rest-after property specifies a prosodic boundary (silence with a specific duration) that occurs after the speech synthesis rendition of an element.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#rest-props-rest-before-after"
|
||||
},
|
||||
"rest": {
|
||||
"desc": "The rest property is a shorthand for rest-before and rest-after.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#rest-props-rest"
|
||||
},
|
||||
"cue-before": {
|
||||
"desc": "The cue-before property specifies auditory icons to be played before the element.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#cue-props-cue-before-after"
|
||||
},
|
||||
"cue-after": {
|
||||
"desc": "The cue-after property specifies auditory icons to be played after the element.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#cue-props-cue-before-after"
|
||||
},
|
||||
"cue": {
|
||||
"desc": "The cue property is a shorthand for cue-before and cue-after.",
|
||||
"spec": "https://drafts.csswg.org/css-speech-1/#cue-props-cue"
|
||||
},
|
||||
"word-boundary-detection": {
|
||||
"desc": "This property allows the author to decide whether and how the user agent must analyse the content to determine where word boundaries are, and to insert virtual word boundaries accordingly.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#word-boundary-detection"
|
||||
},
|
||||
"word-boundary-expansion": {
|
||||
"desc": "This property allows transforming certain word-separating characters into other word-separating characters, to accommodate variant typesetting styles.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#word-boundary-expansion"
|
||||
},
|
||||
"text-space-trim": {
|
||||
"desc": "This property allows authors to specify trimming behavior at the beginning and end of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#white-space-trim"
|
||||
},
|
||||
"hyphenate-limit-zone": {
|
||||
"desc": "This property specifies the maximum amount of unfilled space (before justification) that may be left in the line box before hyphenation is triggered to pull part of a word from the next line back up into the current line.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#hyphenate-size-limits"
|
||||
},
|
||||
"hyphenate-limit-lines": {
|
||||
"desc": "This property indicates the maximum number of successive hyphenated lines in an element. The no-limit value means that there is no limit.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#hyphenate-line-limits"
|
||||
},
|
||||
"hyphenate-limit-last": {
|
||||
"desc": "This property indicates hyphenation behavior at the end of elements, column, pages, and spreads.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#hyphenate-line-limits"
|
||||
},
|
||||
"word-wrap": {
|
||||
"desc": "This property specifies whether the UA may break at otherwise disallowed points within a line to prevent overflow, when an otherwise-unbreakable string is too long to fit within the line box.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#overflow-wrap-property"
|
||||
},
|
||||
"text-wrap": {
|
||||
"desc": "This property specifies the mode for text wrapping.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#text-wrap"
|
||||
},
|
||||
"wrap-before": {
|
||||
"desc": "The wrap-before property specifies modifications to break opportunities in line breaking.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#wrap-before"
|
||||
},
|
||||
"wrap-after": {
|
||||
"desc": "The wrap-after property specifies modifications to break opportunities in line breaking.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#wrap-before"
|
||||
},
|
||||
"wrap-inside": {
|
||||
"desc": "Specifies the line breaking behavior within a box. As determed by the line-breaking rules in effect.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#wrap-inside"
|
||||
},
|
||||
"text-align-all": {
|
||||
"desc": "This longhand of the text-align shorthand property specifies the inline alignment of all lines of inline content in the block container, except for last lines overridden by a non-auto value of text-align-last.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#text-align-all-property"
|
||||
},
|
||||
"text-group-align": {
|
||||
"desc": "This property aligns the contents of the line boxes as a group while maintaining their text alignment.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#text-group-align-property"
|
||||
},
|
||||
"line-padding": {
|
||||
"desc": "Adjusts spacing only at the start/end of a line.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#line-padding-property"
|
||||
},
|
||||
"text-spacing": {
|
||||
"desc": "This property is a shorthand for setting text-spacing-trim and text-autospace in a single declaration.",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#text-spacing-property"
|
||||
},
|
||||
"animation-range-end": {
|
||||
"desc": "Shifts the end time of the animation (i.e. where keyframes mapped to 100% progress are attached when the iteration count is 1) to the specified position on the timeline.",
|
||||
"spec": "https://drafts.csswg.org/scroll-animations-1/#valdef-animation-range-start-timeline-range-name-percentage"
|
||||
},
|
||||
"animation-range-start": {
|
||||
"desc": "Shifts the start time of the animation (i.e. where keyframes mapped to 0% progress are attached when the iteration count is 1) to the specified position on the timeline.",
|
||||
"spec": "https://drafts.csswg.org/scroll-animations-1/#propdef-animation-range-start"
|
||||
},
|
||||
"animation-range": {
|
||||
"desc": "The animation-range property is a shorthand that sets animation-range-start and animation-range-end together in a single declaration.",
|
||||
"spec": "https://drafts.csswg.org/scroll-animations-1/#propdef-animation-range"
|
||||
},
|
||||
"view-timeline": {
|
||||
"desc": "This property is a shorthand for setting view-timeline-name and view-timeline-axis in a single declaration. It does not set view-timeline-inset.",
|
||||
"spec": "https://drafts.csswg.org/scroll-animations-1/#propdef-view-timeline"
|
||||
},
|
||||
"view-timeline-inset": {
|
||||
"desc": "Specifies an inset (positive) or outset (negative) adjustment of the scrollport when determining whether the box is in view when setting the bounds of the corresponding view progress timeline.",
|
||||
"spec": "https://drafts.csswg.org/scroll-animations-1/#propdef-view-timeline-inset"
|
||||
},
|
||||
"view-timeline-axis": {
|
||||
"desc": "Specifies an axis for each named view progress timeline associated with this scroll container.",
|
||||
"spec": "https://drafts.csswg.org/scroll-animations-1/#propdef-view-timeline-axis"
|
||||
},
|
||||
"view-timeline-name": {
|
||||
"desc": "Specifies names for any view progress timelines associated with this element’s principal box.",
|
||||
"spec": "https://drafts.csswg.org/scroll-animations-1/#propdef-view-timeline-name"
|
||||
},
|
||||
"fill-color": {
|
||||
"desc": "This property sets the fill color of an element. This color is drawn behind any fill images.",
|
||||
"spec": "https://drafts.fxtf.org/fill-stroke-3/#fill-color"
|
||||
},
|
||||
"view-transition-name": {
|
||||
"desc": "The view-transition-name property 'names' an element as participating in a view transition.",
|
||||
"spec": "https://drafts.csswg.org/css-view-transitions-1/#view-transition-name-prop"
|
||||
},
|
||||
"input-security": {
|
||||
"desc": "For the purpose of this specification, a sensitive text input is a text input whose purpose is to accept sensitive input, as defined by the host language.",
|
||||
"spec": "https://drafts.csswg.org/css-ui-4/#input-security"
|
||||
},
|
||||
"nav-left": {
|
||||
"desc": "User agents for devices with directional navigation keys respond by navigating the focus according to four respective nav-* directional navigation properties (nav-up, nav-right, nav-down, nav-left).",
|
||||
"spec": "https://drafts.csswg.org/css-ui-4/#nav-dir"
|
||||
},
|
||||
"nav-down": {
|
||||
"desc": "User agents for devices with directional navigation keys respond by navigating the focus according to four respective nav-* directional navigation properties (nav-up, nav-right, nav-down, nav-left).",
|
||||
"spec": "https://drafts.csswg.org/css-ui-4/#nav-dir"
|
||||
},
|
||||
"nav-right": {
|
||||
"desc": "User agents for devices with directional navigation keys respond by navigating the focus according to four respective nav-* directional navigation properties (nav-up, nav-right, nav-down, nav-left).",
|
||||
"spec": "https://drafts.csswg.org/css-ui-4/#nav-dir"
|
||||
},
|
||||
"nav-up": {
|
||||
"desc": "User agents for devices with directional navigation keys respond by navigating the focus according to four respective nav-* directional navigation properties (nav-up, nav-right, nav-down, nav-left).",
|
||||
"spec": "https://drafts.csswg.org/css-ui-4/#nav-dir"
|
||||
},
|
||||
"caret": {
|
||||
"desc": "This property is a shorthand for setting caret-color and caret-shape in one declaration.",
|
||||
"spec": "https://drafts.csswg.org/css-ui-4/#caret"
|
||||
},
|
||||
"caret-shape": {
|
||||
"desc": "This property allows authors to specify the desired shape of the text insertion caret.",
|
||||
"spec": "https://drafts.csswg.org/css-ui-4/#caret-shape"
|
||||
},
|
||||
"text-emphasis-skip": {
|
||||
"desc": "This property describes for which characters marks are drawn.",
|
||||
"spec": "https://drafts.csswg.org/css-text-decor-4/#text-emphasis-skip"
|
||||
},
|
||||
"text-decoration-skip-spaces": {
|
||||
"desc": "This property specifies whether text decoration skips any spaces.",
|
||||
"spec": "https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-spaces-property"
|
||||
},
|
||||
"text-decoration-skip-box": {
|
||||
"desc": "This property specifies what parts of the element’s box area any text decoration affecting the element must skip over.",
|
||||
"spec": "https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-box-property"
|
||||
},
|
||||
"text-decoration-skip-self": {
|
||||
"desc": "This property specifies whether any text decoration lines drawn by its ancestors are propagated to or drawn across the element.",
|
||||
"spec": "https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-self-property"
|
||||
},
|
||||
"text-decoration-trim": {
|
||||
"desc": "This property adjusts the start and end points of line decorations, allowing the author to shorten, lengthen, or shift the decoration with respect to the text.",
|
||||
"spec": "https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-inset-property"
|
||||
},
|
||||
"text-space-collapse": {
|
||||
"desc": "Previous name of 'white-space-collapse'",
|
||||
"spec": "https://drafts.csswg.org/css-text-4/#changes"
|
||||
},
|
||||
"min-intrinsic-sizing": {
|
||||
"desc": "This property defines whether the min-content contribution of a non-replaced box is “compressed” under certain circumstances.",
|
||||
"spec": "https://www.w3.org/TR/css-sizing-4/#intrinsic-contribution-override"
|
||||
},
|
||||
"shape-padding": {
|
||||
"desc": "The shape-padding property adds padding to a shape-inside. This defines a new shape where every point is the specified distance from the shape-inside.",
|
||||
"spec": "https://drafts.csswg.org/css-shapes-2/#propdef-shape-padding"
|
||||
},
|
||||
"shape-inside": {
|
||||
"desc": "The shape-inside property adds one or more exclusion areas to the element’s wrapping context.",
|
||||
"spec": "https://drafts.csswg.org/css-shapes-2/#shape-inside-property"
|
||||
},
|
||||
"scroll-start": {
|
||||
"desc": "This property is a shorthand property that sets all of the scroll-start-* longhands in one declaration.",
|
||||
"spec": "https://drafts.csswg.org/css-scroll-snap-2/#scroll-start"
|
||||
},
|
||||
"scroll-start-target": {
|
||||
"desc": "This property is a shorthand property that sets all of the scroll-start-target-* longhands in one declaration.",
|
||||
"spec": "https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-target"
|
||||
},
|
||||
"scroll-start-x": {
|
||||
"desc": "Defines the scroll starting point in the block axis.",
|
||||
"spec": "https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-longhands-physical"
|
||||
},
|
||||
"scroll-start-y": {
|
||||
"desc": "Defines the scroll starting point in the inline axis.",
|
||||
"spec": "https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-longhands-physical"
|
||||
},
|
||||
"scroll-start-inline": {
|
||||
"desc": "Defines the flow for 'scroll-start' longhands.",
|
||||
"spec": "https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-longhands-logical"
|
||||
},
|
||||
"scroll-start-block": {
|
||||
"desc": "Defines the flow for 'scroll-start' longhands.",
|
||||
"spec": "https://drafts.csswg.org/css-scroll-snap-2/#scroll-start-longhands-logical"
|
||||
},
|
||||
"ruby-overhang": {
|
||||
"desc": "The ruby-overhang property controls whether ruby annotations may overlap adjacent text outside the ruby container.",
|
||||
"spec": "https://drafts.csswg.org/css-ruby-1/#ruby-overhang"
|
||||
},
|
||||
"ruby-merge": {
|
||||
"desc": "This property controls how ruby annotation boxes should be rendered when there are more than one in a ruby container box: whether each pair should be kept separate, the annotations should be merged and rendered as a group, or the separation should be determined based on the space available.",
|
||||
"spec": "https://drafts.csswg.org/css-ruby-1/#collapsed-ruby"
|
||||
},
|
||||
"border-boundary": {
|
||||
"desc": "When the border-boundary property on an element is set to 'parent', additional borders of the element could be drawn where the element’s area and the borders of its parent are met.",
|
||||
"spec": "https://drafts.csswg.org/css-round-display-1/#border-boundary-property"
|
||||
},
|
||||
"block-step": {
|
||||
"desc": "This shorthand property allows for setting block-step-size, block-step-insert, block-step-align, and block-step-round in one declaration.",
|
||||
"spec": "https://www.w3.org/TR/css-rhythm-1/#block-step"
|
||||
},
|
||||
"block-step-round": {
|
||||
"desc": "This property specifies whether adjustments due to block-step-size insert positive or negative space.",
|
||||
"spec": "https://www.w3.org/TR/css-rhythm-1/#block-step-round"
|
||||
},
|
||||
"block-step-align": {
|
||||
"desc": "This property specifies whether extra spacing derived from applying block-step-size is inserted before, inserted after, or split between both sides of the box.",
|
||||
"spec": "https://www.w3.org/TR/css-rhythm-1/#block-step-align"
|
||||
},
|
||||
"block-step-insert": {
|
||||
"desc": "This property specifies whether extra spacing derived from applying block-step-size is inserted inside (like padding) or outside (like margin) the box’s border.",
|
||||
"spec": "https://www.w3.org/TR/css-rhythm-1/#block-step-insert"
|
||||
},
|
||||
"block-step-size": {
|
||||
"desc": "This property defines the step unit for a block-level box’s block size.",
|
||||
"spec": "https://www.w3.org/TR/css-rhythm-1/#block-step-size"
|
||||
},
|
||||
"region-fragment": {
|
||||
"desc": "The region-fragment property controls the behavior of the last usable region associated with a named flow.",
|
||||
"spec": "https://drafts.csswg.org/css-regions-1/#propdef-region-fragment"
|
||||
},
|
||||
"flow-from": {
|
||||
"desc": "The flow-from property makes a block container a region and associates it with a named flow.",
|
||||
"spec": "https://drafts.csswg.org/css-regions-1/#flow-from"
|
||||
},
|
||||
"flow-into": {
|
||||
"desc": "The ‘flow-into’ property can place an element or its contents into a named flow.",
|
||||
"spec": "https://drafts.csswg.org/css-regions-1/#the-flow-into-property"
|
||||
},
|
||||
"page": {
|
||||
"desc": "The page property is used to specify a particular type of page (called a named page) on which an element must be displayed.",
|
||||
"spec": "https://www.w3.org/TR/css-page-3/#using-named-pages"
|
||||
},
|
||||
"float-offset": {
|
||||
"desc": "This property pushes a page float in direction opposite of the where it has been floated with float.",
|
||||
"spec": "https://drafts.csswg.org/css-page-floats-3/#the-float_offset-property"
|
||||
},
|
||||
"float-defer": {
|
||||
"desc": "This property specifies whether the initial float reference of a page float is the fragmentation container in which the float anchor is placed after previous page floats have been placed, or in another one.",
|
||||
"spec": "https://drafts.csswg.org/css-page-floats-3/#float-defer-property"
|
||||
},
|
||||
"float-reference": {
|
||||
"desc": "The floats are aligning to the start or end of a float reference, specified by the float-reference attribute.",
|
||||
"spec": "https://drafts.csswg.org/css-page-floats-3/#float-reference-property"
|
||||
},
|
||||
"max-lines": {
|
||||
"desc": "A property that forces a fragment to break after a specified number of lines.",
|
||||
"spec": "https://www.w3.org/TR/css-overflow-4/#max-lines"
|
||||
},
|
||||
"continue": {
|
||||
"desc": "The continue property gives authors the ability to request that content that does not fit inside an element be fragmented, and provides alternatives for where the remaining content should continue.",
|
||||
"spec": "https://www.w3.org/TR/css-overflow-4/#continue"
|
||||
},
|
||||
"line-clamp": {
|
||||
"desc": "The line-clamp property is a shorthand for the max-lines, block-ellipsis, and continue properties.",
|
||||
"spec": "https://www.w3.org/TR/css-overflow-3/#line-clamp"
|
||||
},
|
||||
"block-ellipsis": {
|
||||
"desc": "This property allows inserting content into the last line box before a (forced or unforced) region break to indicate the continuity of truncated/interrupted content.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#block-ellipsis"
|
||||
},
|
||||
"overflow-clip-margin-block": {
|
||||
"desc": "Defines the overflow clip edge of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#propdef-overflow-clip-margin-block"
|
||||
},
|
||||
"overflow-clip-margin-inline": {
|
||||
"desc": "Defines the overflow clip edge of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#propdef-overflow-clip-margin-inline"
|
||||
},
|
||||
"overflow-clip-margin-inline-end": {
|
||||
"desc": "Defines the overflow clip edge of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#propdef-overflow-clip-margin-inline-end"
|
||||
},
|
||||
"overflow-clip-margin-block-end": {
|
||||
"desc": "Defines the overflow clip edge of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#propdef-overflow-clip-margin-block-end"
|
||||
},
|
||||
"overflow-clip-margin-inline-start": {
|
||||
"desc": "Defines the overflow clip edge of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#propdef-overflow-clip-margin-inline-start"
|
||||
},
|
||||
"overflow-clip-margin-block-start": {
|
||||
"desc": "Defines the overflow clip edge of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#propdef-overflow-clip-margin-block-start"
|
||||
},
|
||||
"overflow-clip-margin-left": {
|
||||
"desc": "Defines the overflow clip edge of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#propdef-overflow-clip-margin-left"
|
||||
},
|
||||
"overflow-clip-margin-bottom": {
|
||||
"desc": "Defines the overflow clip edge of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#propdef-overflow-clip-margin-bottom"
|
||||
},
|
||||
"overflow-clip-margin-right": {
|
||||
"desc": "Defines the overflow clip edge of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#propdef-overflow-clip-margin-right"
|
||||
},
|
||||
"overflow-clip-margin-top": {
|
||||
"desc": "Defines the overflow clip edge of a box.",
|
||||
"spec": "https://drafts.csswg.org/css-overflow-4/#propdef-overflow-clip-margin-top"
|
||||
},
|
||||
"spatial-navigation-function": {
|
||||
"desc": "The default algorithm of spatial navigation specified in the § 8 Processing Model may need the fine tune depending on the layout types.",
|
||||
"spec": "https://www.w3.org/TR/css-nav-1/#css-property-spatialnavigationfunction"
|
||||
},
|
||||
"spatial-navigation-action": {
|
||||
"desc": "When the focus is inside of a scroll container and the user triggers spatial navigation, it is somewhat ambiguous whether they are requesting that the focus be moved in that direction, or whether the document should be scrolled in that direction.",
|
||||
"spec": "https://www.w3.org/TR/css-nav-1/#css-property-spatialnavigationaction"
|
||||
},
|
||||
"spatial-navigation-contain": {
|
||||
"desc": "Creates an additional spatial navigation container.",
|
||||
"spec": "https://www.w3.org/TR/css-nav-1/#container"
|
||||
},
|
||||
"marker-side": {
|
||||
"desc": "The marker-side property specifies whether an outside marker box is positioned based on the directionality of the list item itself (i.e. its originating element) or the directionality of the list container (i.e. the originating element’s parent).",
|
||||
"spec": "https://www.w3.org/TR/css-lists-3/#marker-side"
|
||||
},
|
||||
"link-parameters": {
|
||||
"desc": "The link-parameters property is one way to set link parameters on the element itself, and on all external CSS resources specified on the element.",
|
||||
"spec": "https://drafts.csswg.org/css-link-params-1/#link-param-prop"
|
||||
},
|
||||
"box-snap": {
|
||||
"desc": "Specifies how the block is snapped to the baseline grid.",
|
||||
"spec": "https://www.w3.org/TR/css-line-grid-1/#box-snap"
|
||||
},
|
||||
"line-snap": {
|
||||
"desc": "This property applies to all the line boxes directly contained by the element, and, when not none, causes each line box to shift (usually downward, possibly by zero) until it snaps to the line grid specified by line-grid.",
|
||||
"spec": "https://www.w3.org/TR/css-line-grid-1/#line-snap"
|
||||
},
|
||||
"line-grid": {
|
||||
"desc": "Specifies whether this box creates a new baseline grid for its descendants or uses the same baseline grid as its parent.",
|
||||
"spec": "https://www.w3.org/TR/css-line-grid-1/#line-grid"
|
||||
},
|
||||
"initial-letter-wrap": {
|
||||
"desc": "This property specifies whether lines impacted by an initial letter are shortened to fit the rectangular shape of the initial letter box or the contour of its glyph outline.",
|
||||
"spec": "https://www.w3.org/TR/css-inline-3/#initial-letter-wrapping"
|
||||
},
|
||||
"inline-sizing": {
|
||||
"desc": "This property specifies how the logical height of the content area of an inline box is measured in relation to its contents.",
|
||||
"spec": "https://www.w3.org/TR/css-inline-3/#line-fill"
|
||||
},
|
||||
"leading-trim": {
|
||||
"desc": "On inline boxes, specifies whether to trim the content box to match its corresponding text-edge metric.",
|
||||
"spec": "https://www.w3.org/TR/css-inline-3/#propdef-leading-trim"
|
||||
},
|
||||
"text-edge": {
|
||||
"desc": "Inline boxes, whose primary purpose is to contain text, are sized in the block axis based on their font metrics.",
|
||||
"spec": "https://www.w3.org/TR/css-inline-3/#propdef-text-edge"
|
||||
},
|
||||
"baseline-source": {
|
||||
"desc": "When an inline-level box has more than one possible source for baseline information (such as for a multi-line inline block or inline flex container) this property specifies whether the first baseline set or last baseline set is preferred for alignment, indicating the box’s baseline alignment preference.",
|
||||
"spec": "https://www.w3.org/TR/css-inline-3/#baseline-source"
|
||||
},
|
||||
"object-view-box": {
|
||||
"desc": "The object-view-box property specifies a 'view box' over an element, which allows zooming or panning over the element’s contents.",
|
||||
"spec": "https://drafts.csswg.org/css-images-5/#the-object-view-box"
|
||||
},
|
||||
"string-set": {
|
||||
"desc": "The string-set property contains one or more pairs, each consisting of an custom identifier (the name of the named string) followed by a content-list describing how to construct the value of the named string.",
|
||||
"spec": "https://drafts.csswg.org/css-gcpm-3/#setting-named-strings-the-string-set-pro"
|
||||
},
|
||||
"bookmark-level": {
|
||||
"desc": "The bookmark-level property determines if a bookmark is created, and at what level.",
|
||||
"spec": "https://drafts.csswg.org/css-content-3/#propdef-bookmark-level"
|
||||
},
|
||||
"bookmark-label": {
|
||||
"desc": "Sets the text content of the bookmark label.",
|
||||
"spec": "https://drafts.csswg.org/css-content-3/#bookmark-label"
|
||||
},
|
||||
"bookmark-state": {
|
||||
"desc": "The bookmark-state may be open or closed.",
|
||||
"spec": "https://drafts.csswg.org/css-content-3/#bookmark-state"
|
||||
},
|
||||
"footnote-policy": {
|
||||
"desc": "The footnote-policy property allows authors some influence over the rendering of difficult pages.",
|
||||
"spec": "https://drafts.csswg.org/css-gcpm-3/#footnote-policy"
|
||||
},
|
||||
"footnote-display": {
|
||||
"desc": "The footnote-display property determines whether a footnote is displayed as a block element or inline element.",
|
||||
"spec": "https://drafts.csswg.org/css-gcpm-3/#footnote-types"
|
||||
},
|
||||
"reading-order": {
|
||||
"desc": "The reading-order property controls the order in which elements are rendered to speech or are navigated to when using (linear) sequention navigation methods.",
|
||||
"spec": "https://drafts.csswg.org/css-display-4/#reading-order"
|
||||
},
|
||||
"layout-order": {
|
||||
"desc": "By allowing the layout to be rearranged without affecting the underlying document source order, the layout-order property lets authors keep a document’s reading and interaction order matched to the visual perception order in cases where it does not match the layout order.",
|
||||
"spec": "https://drafts.csswg.org/css-display-4/#layout-order"
|
||||
},
|
||||
"font-synthesis-weight": {
|
||||
"desc": "This property controls whether user agents are allowed to synthesize bold font faces when a font family lacks bold faces.",
|
||||
"spec": "https://drafts.csswg.org/css-fonts-4/#font-synthesis-weightThis property controls whether user agents are allowed to synthesize bold font faces when a font family lacks bold faces."
|
||||
},
|
||||
"font-synthesis-style": {
|
||||
"desc": "This property controls whether user agents are allowed to synthesize oblique font faces when a font family lacks oblique faces.",
|
||||
"spec": "https://drafts.csswg.org/css-fonts-4/#font-synthesis-style"
|
||||
},
|
||||
"font-synthesis-small-caps": {
|
||||
"desc": "This property controls whether user agents are allowed to synthesize small caps font faces when a font family lacks small caps faces.",
|
||||
"spec": "https://drafts.csswg.org/css-fonts-4/#font-synthesis-small-caps"
|
||||
},
|
||||
"margin-break": {
|
||||
"desc": "Controls whether the box’s block-axis margins are discarded or kept at a fragmentation break.",
|
||||
"spec": "https://www.w3.org/TR/css-break-4/#break-margins"
|
||||
},
|
||||
"color-adjust": {
|
||||
"desc": "The color-adjust shorthand allows an author to set all of the performance-motivated color adjustment properties in one declaration.",
|
||||
"spec": "https://www.w3.org/TR/css-color-adjust-1/#color-adjust"
|
||||
},
|
||||
"wrap-flow": {
|
||||
"desc": "An element becomes an exclusion when its wrap-flow property has a computed value other than auto.",
|
||||
"spec": "https://drafts.csswg.org/css-exclusions-1/#wrap-flow-property"
|
||||
},
|
||||
"wrap-through": {
|
||||
"desc": "Setting the wrap-through property to none prevents an element from inheriting its parent wrapping context.",
|
||||
"spec": "https://drafts.csswg.org/css-exclusions-1/#wrap-through-property"
|
||||
},
|
||||
"copy-into": {
|
||||
"desc": "The copy-into property contains one or more pairs, each consisting of a custom identifier followed by a content-level keyword describing how to construct the value of the named content fragment.",
|
||||
"spec": "https://drafts.csswg.org/css-gcpm-4/#copy-into-heading"
|
||||
}
|
||||
}
|
17324
packages/autocomplete-css/package-lock.json
generated
Normal file
17324
packages/autocomplete-css/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
packages/autocomplete-css/package.json
Normal file
23
packages/autocomplete-css/package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"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": {
|
||||
"@webref/css": "^6.3.4",
|
||||
"content": "github:mdn/content",
|
||||
"request": "^2.53.0"
|
||||
}
|
||||
}
|
929
packages/autocomplete-css/spec/provider-spec.coffee
Normal file
929
packages/autocomplete-css/spec/provider-spec.coffee
Normal file
@ -0,0 +1,929 @@
|
||||
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'
|
||||
|
||||
# Throughout the entirety of this test document there are many places that the
|
||||
# original Atom tests would check for exact values of returned items such as
|
||||
# matching properties or matching tags. But as the web changes this is
|
||||
# combersome to maintain, to do Pulsar's best to avoid regressions in this aspect
|
||||
# these locations will now check for more than the last good value.
|
||||
# This of course assumes that the web won't start removing matching items faster
|
||||
# than adding. But locations of this behavior will be marked accordingly with: #398
|
||||
# https://github.com/pulsar-edit/pulsar/pull/398
|
||||
|
||||
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)
|
||||
|
||||
isValueInCompletions = (value, completions) ->
|
||||
completionsNodesText = []
|
||||
for completion in completions
|
||||
completionsNodesText.push(completion.text)
|
||||
return value in completionsNodesText
|
||||
|
||||
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.length).toBeGreaterThan 9 # #398
|
||||
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).toBeGreaterThan 237 # #398 Fun Fact last check this was 673
|
||||
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(isValueInCompletions('display: ', completions)).toBe true
|
||||
expect(isValueInCompletions('direction: ', completions)).toBe true
|
||||
|
||||
# Then no matter what the top results are there's still some we can expect of them.
|
||||
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].type).toBe 'property'
|
||||
expect(completions[1].replacementPrefix).toBe 'd'
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
D
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 2 # #398
|
||||
expect(isValueInCompletions('display: ', completions)).toBe true
|
||||
expect(isValueInCompletions('direction: ', completions)).toBe true
|
||||
|
||||
expect(completions[1].replacementPrefix).toBe 'D'
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
d:
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions()
|
||||
expect(isValueInCompletions('display: ', completions)).toBe true
|
||||
expect(isValueInCompletions('direction: ', completions)).toBe true
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
bord
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 6])
|
||||
completions = getCompletions()
|
||||
expect(isValueInCompletions('border: ', completions)).toBe true
|
||||
|
||||
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(isValueInCompletions('width: ', completions)).toBe true
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 0])
|
||||
completions = getCompletions()
|
||||
expect(isValueInCompletions('width: ', completions)).toBe true
|
||||
|
||||
editor.setText """
|
||||
body { }
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
completions = getCompletions()
|
||||
expect(isValueInCompletions('width: ', completions)).toBe true
|
||||
|
||||
editor.setText """
|
||||
body { }
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 7])
|
||||
completions = getCompletions()
|
||||
expect(isValueInCompletions('width: ', completions)).toBe true
|
||||
|
||||
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).toBeGreaterThan 24 # #398
|
||||
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).toBeGreaterThan 24 # #398
|
||||
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(isValueInCompletions('inline;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-block;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-flex;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-grid;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-table;', completions)).toBe true
|
||||
expect(isValueInCompletions('inherit;', completions)).toBe true
|
||||
expect(completions[0].description.length).toBeGreaterThan 0
|
||||
expect(completions[0].descriptionMoreURL.length).toBeGreaterThan 0
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
display: I
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 12])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 6 # #398
|
||||
expect(isValueInCompletions('inline;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-block;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-flex;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-grid;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-table;', completions)).toBe true
|
||||
expect(isValueInCompletions('inherit;', completions)).toBe true
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
display:
|
||||
i
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([2, 5])
|
||||
completions = getCompletions()
|
||||
expect(isValueInCompletions('inline;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-block;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-flex;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-grid;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-table;', completions)).toBe true
|
||||
expect(isValueInCompletions('inherit;', completions)).toBe true
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
text-align:
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 13])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 5 # #398
|
||||
expect(isValueInCompletions('center;', completions)).toBe true
|
||||
expect(isValueInCompletions('left;', completions)).toBe true
|
||||
expect(isValueInCompletions('justify;', completions)).toBe true
|
||||
expect(isValueInCompletions('right;', completions)).toBe true
|
||||
expect(isValueInCompletions('inherit;', completions)).toBe true
|
||||
|
||||
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.length).toBeGreaterThan 24 # #398
|
||||
expect(isValueInCompletions('block;', completions)).toBe true
|
||||
|
||||
editor.setText """
|
||||
body {
|
||||
display: block; float:
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 24])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 4 # #398
|
||||
expect(isValueInCompletions('left;', completions)).toBe true
|
||||
|
||||
it "autocompletes more than one inline property value", ->
|
||||
editor.setText "body { display: block; float: }"
|
||||
editor.setCursorBufferPosition([0, 30])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 4 # #398
|
||||
expect(isValueInCompletions('left;', completions)).toBe true
|
||||
|
||||
editor.setText "body { display: block; float: left; cursor: alias; text-decoration: }"
|
||||
editor.setCursorBufferPosition([0, 68])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 5 # #398
|
||||
expect(isValueInCompletions('line-through;', completions)).toBe true
|
||||
|
||||
it "autocompletes inline property values with a prefix", ->
|
||||
editor.setText "body { display: i }"
|
||||
editor.setCursorBufferPosition([0, 17])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 6 # #398
|
||||
expect(isValueInCompletions('inline;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-block;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-flex;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-grid;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-table;', completions)).toBe true
|
||||
expect(isValueInCompletions('inherit;', completions)).toBe true
|
||||
|
||||
editor.setText "body { display: i}"
|
||||
editor.setCursorBufferPosition([0, 17])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 6 # #398
|
||||
expect(isValueInCompletions('inline;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-block;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-flex;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-grid;', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-table;', completions)).toBe true
|
||||
expect(isValueInCompletions('inherit;', completions)).toBe true
|
||||
|
||||
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.length).toBeGreaterThan 4 # #398
|
||||
expect(isValueInCompletions('left;', completions)).toBe true
|
||||
expect(isValueInCompletions('right;', completions)).toBe true
|
||||
expect(isValueInCompletions('none;', completions)).toBe true
|
||||
expect(isValueInCompletions('inherit;', completions)).toBe true
|
||||
|
||||
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).toBeGreaterThan 7 # #398
|
||||
expect(isValueInCompletions('canvas', completions)).toBe true
|
||||
expect(isValueInCompletions('code', completions)).toBe true
|
||||
|
||||
expect(completions[0].type).toBe 'tag'
|
||||
expect(completions[0].description.length).toBeGreaterThan 0
|
||||
|
||||
editor.setText """
|
||||
canvas,ca {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 7 # #398
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
|
||||
editor.setText """
|
||||
canvas ca {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 7 # #398
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
|
||||
editor.setText """
|
||||
canvas, ca {
|
||||
}
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 10])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 7 # #398
|
||||
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).toBeGreaterThan 5 # #398
|
||||
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).toBeGreaterThan 4 # #398
|
||||
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(isValueInCompletions('display: ', completions)).toBe true
|
||||
expect(isValueInCompletions('direction: ', completions)).toBe true
|
||||
expect(isValueInCompletions('div', completions)).toBe true
|
||||
|
||||
# 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(isValueInCompletions('display: ', completions)).toBe true
|
||||
expect(isValueInCompletions('direction: ', completions)).toBe true
|
||||
|
||||
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].type).toBe 'property'
|
||||
expect(completions[1].replacementPrefix).toBe 'd'
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
D
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 11 # #398
|
||||
expect(isValueInCompletions('display: ', completions)).toBe true
|
||||
expect(isValueInCompletions('direction: ', completions)).toBe true
|
||||
|
||||
expect(completions[1].replacementPrefix).toBe 'D'
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
d:
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 3])
|
||||
completions = getCompletions()
|
||||
expect(isValueInCompletions('display: ', completions)).toBe true
|
||||
expect(isValueInCompletions('direction: ', completions)).toBe true
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
bord
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 6])
|
||||
completions = getCompletions()
|
||||
expect(isValueInCompletions('border: ', completions)).toBe true
|
||||
|
||||
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).toBeGreaterThan 24 # #398
|
||||
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).toBeGreaterThan 24 # #398
|
||||
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(isValueInCompletions('inline', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-block', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-flex', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-grid', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-table', completions)).toBe true
|
||||
expect(isValueInCompletions('inherit', completions)).toBe true
|
||||
|
||||
expect(completions[0].description.length).toBeGreaterThan 0
|
||||
expect(completions[0].descriptionMoreURL.length).toBeGreaterThan 0
|
||||
|
||||
editor.setText """
|
||||
body
|
||||
display: I
|
||||
"""
|
||||
editor.setCursorBufferPosition([1, 12])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 6 # #398
|
||||
|
||||
expect(isValueInCompletions('inline', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-block', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-flex', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-grid', completions)).toBe true
|
||||
expect(isValueInCompletions('inline-table', completions)).toBe true
|
||||
expect(isValueInCompletions('inherit', completions)).toBe true
|
||||
|
||||
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(isValueInCompletions('border: ', completions)).toBe true
|
||||
expect(isValueInCompletions('border-radius: ', completions)).toBe true
|
||||
|
||||
expect(completions[0].replacementPrefix).toBe 'border-'
|
||||
|
||||
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).toBeGreaterThan 7 # #398
|
||||
expect(isValueInCompletions('canvas', completions)).toBe true
|
||||
expect(isValueInCompletions('code', completions)).toBe true
|
||||
|
||||
expect(completions[0].type).toBe 'tag'
|
||||
expect(completions[0].description.length).toBeGreaterThan 0
|
||||
|
||||
editor.setText """
|
||||
canvas,ca
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 7 # #398
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
|
||||
editor.setText """
|
||||
canvas ca
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 7 # #398
|
||||
expect(completions[0].text).toBe 'canvas'
|
||||
|
||||
editor.setText """
|
||||
canvas, ca
|
||||
"""
|
||||
editor.setCursorBufferPosition([0, 10])
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan 7 # #398
|
||||
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'
|
368
packages/autocomplete-css/update.js
Normal file
368
packages/autocomplete-css/update.js
Normal file
@ -0,0 +1,368 @@
|
||||
/**
|
||||
This file will manage the updating of `autocomplete-css` `completions.json`.
|
||||
We will mainly utilize `@webref/css`.listAll() function that returns a full CSS
|
||||
list of all properties seperated by their spec shortname. An example
|
||||
of this format is defined below for ease of future modifications.
|
||||
|
||||
Some important notes about the data contained here:
|
||||
- Often times the `value` within the `property` will be in the following format:
|
||||
`<valueGroupName>` or even `<valueGroupName> | value | value2` or just `value | value2`
|
||||
It will be important to build a parser that can handle this format.
|
||||
The `<valueGroupName>` then can be realized via that specs `values` where
|
||||
`values[x].name` will match the `<valueGroupName>`. Another important note about
|
||||
handling values here is that oftentimes `values[x].values[]` won't actually
|
||||
contain all possible values. And instead this must be handled by checking
|
||||
`values[x].value` which is another string of `<valueGroupName> | value`.
|
||||
So this should be handled by the same parser.
|
||||
- Additionally an important note is that nowhere in this data do we get any kind
|
||||
of description about the data that could lend a hand in being documentation.
|
||||
So the documentation must be gathered seperatly. Likely the best way to collect
|
||||
our documentation data is via `mdn/content`.
|
||||
Within `content/files/en-us/web/css` is a directory of folders titled
|
||||
by the name of properties.
|
||||
|
||||
The last important thing to note here:
|
||||
MDN doesn't have docs on everything. And that's a good thing. But it means
|
||||
many of our items don't have any kind of description. For this situation
|
||||
we have `manual-property-desc.json` which is a list of manually updated
|
||||
descriptions for properties where there are none. This was a last resort
|
||||
intended to provide the highest quality of completions possible.
|
||||
Overtime many items on this list will likely be able to be removed just as
|
||||
new ones are added. After running the update script you'll see a warning
|
||||
saying how many properties are without completions that would then need to
|
||||
be added to the JSON file.
|
||||
|
||||
"spec-shortname": {
|
||||
"spec": {
|
||||
"title": "",
|
||||
"url": ""
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "",
|
||||
"value": "",
|
||||
"initial": "",
|
||||
"appliesTo": "",
|
||||
"percentages": "",
|
||||
"computedValue": "",
|
||||
"canonicalOrder": "",
|
||||
"animationType": "",
|
||||
"media": "",
|
||||
"styleDeclaration": [ "", "", "" ]
|
||||
}
|
||||
],
|
||||
"atrules": [
|
||||
{
|
||||
"name": "",
|
||||
"descriptors": [
|
||||
{
|
||||
"name": "",
|
||||
"for": "",
|
||||
"value": "",
|
||||
"type": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"selectors": [],
|
||||
"values": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "",
|
||||
"prose": "Optional description",
|
||||
"value": "",
|
||||
"values": [
|
||||
{
|
||||
"name": "",
|
||||
"prose": "Optional Description",
|
||||
"type": "",
|
||||
"value": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"warnings": []
|
||||
}
|
||||
*/
|
||||
|
||||
const css = require("@webref/css");
|
||||
const fs = require("fs");
|
||||
const CSSParser = require("./cssValueDefinitionSyntaxExtractor.js");
|
||||
const manualPropertyDesc = require("./manual-property-desc.json");
|
||||
|
||||
async function update(params) {
|
||||
const parsedFiles = await css.listAll();
|
||||
|
||||
const properties = await buildProperties(parsedFiles);
|
||||
const tags = await getTagsHTML();
|
||||
const pseudoSelectors = await getPseudoSelectors();
|
||||
|
||||
const completions = {
|
||||
tags: tags,
|
||||
properties: properties,
|
||||
pseudoSelectors: pseudoSelectors
|
||||
};
|
||||
|
||||
// Now to write out our updated file
|
||||
fs.writeFileSync("completions.json", JSON.stringify(completions, null, 2));
|
||||
|
||||
// Now to determine how many properties have empty descriptions.
|
||||
|
||||
let count = 0;
|
||||
let showEmpty = false;
|
||||
|
||||
for (const param of params) {
|
||||
if (param === "--show-empty") {
|
||||
showEmpty = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (const prop in completions.properties) {
|
||||
if (completions.properties[prop].description === "") {
|
||||
if (showEmpty) {
|
||||
console.log(prop);
|
||||
}
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Updated all `autocomplete-css` completions.");
|
||||
console.log(`Total Completion Properties without a description: ${count}!`);
|
||||
if (count !== 0) {
|
||||
console.log("It is not required to fix the above empty completions issue.");
|
||||
console.log("Use `node update.js --show-empty` to show the empty property names.");
|
||||
};
|
||||
}
|
||||
|
||||
async function buildProperties(css) {
|
||||
// This function will take a CSS object of all values from @webref/css
|
||||
// and will gather descriptions from mdn/content for these properties.
|
||||
// Returning data in the expected format for the old fashioned `completions.json`
|
||||
|
||||
let propertyObj = {};
|
||||
|
||||
for (const spec in css) {
|
||||
|
||||
// For now we will only retain `properties` in these files. At a later time
|
||||
// we can revist and looking at adding `atrules`
|
||||
if (Array.isArray(css[spec].properties)) {
|
||||
for (const prop of css[spec].properties) {
|
||||
|
||||
const propDescription = await getDescriptionOfProp(prop.name);
|
||||
const propValues = getValuesOfProp(prop.value, css);
|
||||
|
||||
if (typeof propertyObj[prop.name] !== "object") {
|
||||
propertyObj[prop.name] = {
|
||||
values: dedupPropValues(propValues),
|
||||
description: propDescription
|
||||
};
|
||||
} else {
|
||||
// So seems this happens way more often than assumed.
|
||||
// So instead of discard a previously entered entry, we will prioritize
|
||||
// having values accomponing it. So whoever has the longer array of
|
||||
// values will be used as the tiebreaker.
|
||||
if (propertyObj[prop.name].values.length < propValues.length) {
|
||||
propertyObj[prop.name] = {
|
||||
values: dedupPropValues(propValues),
|
||||
description: propDescription
|
||||
};
|
||||
}
|
||||
}
|
||||
// Unfortunately the no duplication guarantee of @webref/css seems
|
||||
// inaccurate. As there are duplicate `display` definitions.
|
||||
// The first containing all the data we want, and the later containing nothing.
|
||||
// This protects against overriding previously definied definitions.
|
||||
|
||||
}
|
||||
} // else continue our loop
|
||||
}
|
||||
|
||||
return propertyObj;
|
||||
}
|
||||
|
||||
async function getDescriptionOfProp(name) {
|
||||
// We will gather a description by checking if there's a document written
|
||||
// on MDN for our property and then extract a summary from there.
|
||||
|
||||
// Since not all CSS property definitions will exist within the CSS docs
|
||||
// While this seems strange, it's because some selectors are part of other
|
||||
// specs and may not be worth mentioning standalone.
|
||||
let file;
|
||||
let filePath = [ "css", "svg/attribute", "svg/element" ].map(path =>
|
||||
`./node_modules/content/files/en-us/web/${path}/${name}/index.md`
|
||||
).find(f => fs.existsSync(f));
|
||||
|
||||
if (filePath) {
|
||||
file = fs.readFileSync(filePath, { encoding: "utf8" });
|
||||
}
|
||||
|
||||
if (file) {
|
||||
// Here we will do a quick and dirty way to parse the markdown file to retreive a raw string
|
||||
let breaks = file.split("---");
|
||||
|
||||
// The first two breaks should be the yaml metadata block
|
||||
let data = breaks[2].replace(/\{\{\S+\}\}\{\{\S+\}\}/gm, "")
|
||||
.replace(/\{\{CSSRef\}\}/gm, "")
|
||||
.replace(/\{\{SVGRef\}\}/gm, "");
|
||||
let summaryRaw = data.split("\n");
|
||||
// In case the first few lines is an empty line break
|
||||
for (let i = 0; i < summaryRaw.length; i++) {
|
||||
// Filtering the starting character protects agains't collecting accidental
|
||||
// warnings or other notices within the MDN site.
|
||||
if (summaryRaw[i].length > 1 && !summaryRaw[i].startsWith("> ") && !summaryRaw[i].startsWith("« ")) {
|
||||
return summaryRaw[i]
|
||||
.replace(/\{\{\S+\("(\S+)"\)\}\}/g, '$1')
|
||||
.replace(/\*/g, "")
|
||||
.replace(/\`/g, "")
|
||||
.replace(/\{/g, "")
|
||||
.replace(/\}/g, "")
|
||||
.replace(/\"/g, "")
|
||||
.replace(/\_/g, "")
|
||||
.replace(/\[([A-Za-z0-9-_* ]+)\]\(\S+\)/g, '$1');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// A document doesn't yet exist, let's ensure it's not in our manual list first
|
||||
if (manualPropertyDesc[name]) {
|
||||
return manualPropertyDesc[name].desc;
|
||||
}
|
||||
// A document doesn't yet exist. And it's not in our manual list
|
||||
// Let's return an empty value.
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function getValuesOfProp(value, allValues, appendImplicitValues=true) {
|
||||
// value holds the value string of the values we expect
|
||||
// allValues holds all of the values that apply to the spec
|
||||
// Like mentioned above `value` = "value1 | value2 | <valueGroupName>"
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/Value_definition_syntax
|
||||
|
||||
// We will at least supply the implicitly defined keywords that apply to all CSS properties
|
||||
let implicitValues = [ "inherit", "initial", "unset" ];
|
||||
|
||||
if (!value) {
|
||||
if (appendImplicitValues === true) {
|
||||
return implicitValues;
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
let values = [];
|
||||
let parser = new CSSParser(value);
|
||||
|
||||
let rawArrayValues = parser.parse();
|
||||
|
||||
for (const val of rawArrayValues) {
|
||||
if (val.length > 1) {
|
||||
// Since some values contain `||` some splits leave a zero length string
|
||||
if (val.trim().startsWith("<") && val.trim().endsWith(">")) {
|
||||
// This is a valueGroup lookup key
|
||||
let valueGroup = parseValueGroup(val.trim(), allValues);
|
||||
values = values.concat(valueGroup);
|
||||
} else {
|
||||
values.push(val.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appendImplicitValues === true) {
|
||||
// Add the implicit values to the end...
|
||||
values = values.concat(implicitValues);
|
||||
};
|
||||
|
||||
return values;
|
||||
|
||||
}
|
||||
|
||||
function parseValueGroup(valueGroupName, allValues) {
|
||||
// Will lookup a valueGroup name within allValues and parse it
|
||||
|
||||
let resolvedValueGroupString;
|
||||
|
||||
// Now we can receive two kinds of Basic Data Types here
|
||||
// - Non-Terminal Data Types: <'valueGroupName'> which will share the name of a property
|
||||
// - And the standard that this was built to deal with.
|
||||
|
||||
if (valueGroupName.startsWith("<'") && valueGroupName.endsWith("'>")) {
|
||||
// Non-Terminal Data Types
|
||||
for (const spec in allValues) {
|
||||
if (Array.isArray(allValues[spec].properties)) {
|
||||
for (const prop of allValues[spec].properties) {
|
||||
if (prop.name === valueGroupName.replace("<'", "").replace("'>", "")) {
|
||||
resolvedValueGroupString = prop.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Standard handling
|
||||
for (const spec in allValues) {
|
||||
if (Array.isArray(allValues[spec].values)) {
|
||||
for (const val of allValues[spec].values) {
|
||||
if (val.name === valueGroupName) {
|
||||
resolvedValueGroupString = val.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return getValuesOfProp(resolvedValueGroupString, allValues=null, appendImplicitValues=false);
|
||||
}
|
||||
|
||||
async function getTagsHTML() {
|
||||
// This will also use our dep of `mdn/content` to find all tags currently
|
||||
// within their docs. By simply grabbing all folders of tag docs by their name
|
||||
|
||||
// Some of the page titles from MDN's docs don't accurately reflect what we
|
||||
// would expect to appear. The object below is named after what the name of the
|
||||
// folder from MDN's docs is called, whose value is then the array we would instead expect.
|
||||
const replaceTags = {
|
||||
"heading_elements": [ "h1", "h2", "h3", "h4", "h5", "h6" ],
|
||||
};
|
||||
|
||||
let tags = [];
|
||||
|
||||
let files = fs.readdirSync("./node_modules/content/files/en-us/web/html/element");
|
||||
|
||||
files.forEach(file => {
|
||||
if (file != "index.md") {
|
||||
if (Array.isArray(replaceTags[file])) {
|
||||
tags = tags.concat(replaceTags[file]);
|
||||
} else {
|
||||
tags.push(file);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
async function getPseudoSelectors() {
|
||||
// For now since there is no best determined way to collect all modern psudoselectors
|
||||
// We will just grab the existing list for our existing `completions.json`
|
||||
|
||||
let existingCompletions = require("./completions.json");
|
||||
|
||||
return existingCompletions.pseudoSelectors;
|
||||
}
|
||||
|
||||
function dedupPropValues(values) {
|
||||
// Takes an array of values and returns an array without any duplicates
|
||||
let out = [];
|
||||
let check = {};
|
||||
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
if (!check[values[i]]) {
|
||||
out.push(values[i]);
|
||||
check[values[i]] = true;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
update(process.argv.slice(2));
|
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 `npm run update` at the root of the package and then checking-in the changed `completions.json` file.
|
14540
packages/autocomplete-html/completions.json
Normal file
14540
packages/autocomplete-html/completions.json
Normal file
File diff suppressed because it is too large
Load Diff
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)}#attributes`
|
||||
}
|
||||
|
||||
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
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user