Merge remote-tracking branch 'origin/master' into patch-1

This commit is contained in:
David Wilson
2018-09-06 07:10:51 -07:00
230 changed files with 35006 additions and 2026 deletions

View File

@@ -15,7 +15,7 @@ matrix:
include:
- os: linux
dist: trusty
env: NODE_VERSION=6.9.4 DISPLAY=:99.0 CC=clang CXX=clang++ npm_config_clang=1
env: NODE_VERSION=8.9.3 DISPLAY=:99.0 CC=clang CXX=clang++ npm_config_clang=1
sudo: required
@@ -27,7 +27,7 @@ install:
- source /tmp/.nvm/nvm.sh
- nvm install $NODE_VERSION
- nvm use --delete-prefix $NODE_VERSION
- npm install -g npm@5.3.0
- npm install --global npm@6.2.0
- script/build --create-debian-package --create-rpm-package --compress-artifacts
script:

View File

@@ -1,6 +1,6 @@
![Atom](https://cloud.githubusercontent.com/assets/72919/2874231/3af1db48-d3dd-11e3-98dc-6066f8bc766f.png)
[![macOS Build Status](https://circleci.com/gh/atom/atom/tree/master.svg?style=shield)](https://circleci.com/gh/atom/atom) [![Linux Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom)
[![Build status](https://github.visualstudio.com/Atom/_apis/build/status/Atom%20Production%20Branches?branch=master)](https://github.visualstudio.com/Atom/_build/latest?definitionId=32&branch=master) [![Linux Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom)
[![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom)
[![Join the Atom Community on Slack](https://atom-slack.herokuapp.com/badge.svg)](https://atom-slack.herokuapp.com)

4522
apm/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,6 @@
"url": "https://github.com/atom/atom.git"
},
"dependencies": {
"atom-package-manager": "1.19.0"
"atom-package-manager": "2.1.1"
}
}

View File

@@ -20,7 +20,7 @@ environment:
global:
ATOM_DEV_RESOURCE_PATH: c:\projects\atom
TEST_JUNIT_XML_ROOT: c:\projects\junit-test-results
NODE_VERSION: 6.9.4
NODE_VERSION: 8.9.3
matrix:
- TASK: test
@@ -36,7 +36,7 @@ install:
- IF NOT EXIST %TEST_JUNIT_XML_ROOT% MKDIR %TEST_JUNIT_XML_ROOT%
- SET PATH=C:\Program Files\Atom\resources\cli;%PATH%
- ps: Install-Product node $env:NODE_VERSION $env:PLATFORM
- npm install -g npm@5.3.0
- npm install --global npm@6.2.0
build_script:
- CD %APPVEYOR_BUILD_FOLDER%
@@ -78,6 +78,12 @@ artifacts:
name: atom-windows.zip
- path: out\RELEASES
name: RELEASES
- path: out\AtomSetup-x64.exe
name: AtomSetup-x64.exe
- path: out\atom-x64-windows.zip
name: atom-x64-windows.zip
- path: out\RELEASES-x64
name: RELEASES-x64
- path: out\atom-*-delta.nupkg
name: atom-delta.nupkg
- path: out\atom-*-full.nupkg

22
atom.sh
View File

@@ -13,6 +13,9 @@ case $(basename $0) in
atom-beta)
CHANNEL=beta
;;
atom-nightly)
CHANNEL=nightly
;;
atom-dev)
CHANNEL=dev
;;
@@ -76,10 +79,20 @@ if [ $OS == 'Mac' ]; then
ATOM_APP_NAME="$(basename "$ATOM_APP")"
fi
if [ "$CHANNEL" == 'beta' ]; then
ATOM_EXECUTABLE_NAME="Atom Beta"
if [ ! -z "${ATOM_APP_NAME}" ]; then
# If ATOM_APP_NAME is known, use it as the executable name
ATOM_EXECUTABLE_NAME="${ATOM_APP_NAME%.*}"
else
ATOM_EXECUTABLE_NAME="Atom"
# Else choose it from the inferred channel name
if [ "$CHANNEL" == 'beta' ]; then
ATOM_EXECUTABLE_NAME="Atom Beta"
elif [ "$CHANNEL" == 'nightly' ]; then
ATOM_EXECUTABLE_NAME="Atom Nightly"
elif [ "$CHANNEL" == 'dev' ]; then
ATOM_EXECUTABLE_NAME="Atom Dev"
else
ATOM_EXECUTABLE_NAME="Atom"
fi
fi
if [ -z "${ATOM_PATH}" ]; then
@@ -114,6 +127,9 @@ elif [ $OS == 'Linux' ]; then
beta)
ATOM_PATH="$USR_DIRECTORY/share/atom-beta/atom"
;;
nightly)
ATOM_PATH="$USR_DIRECTORY/share/atom-nightly/atom"
;;
dev)
ATOM_PATH="$USR_DIRECTORY/share/atom-dev/atom"
;;

View File

@@ -1,45 +0,0 @@
machine:
environment:
XCODE_SCHEME: test
XCODE_WORKSPACE: test
XCODE_PROJECT: test
TEST_JUNIT_XML_ROOT: ${CIRCLE_TEST_REPORTS}
xcode:
version: 7.3
general:
artifacts:
- out/atom-mac.zip
- out/atom-mac-symbols.zip
- docs/output/atom-api.json
dependencies:
pre:
- curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash
- nvm install 6.9.4
- nvm use 6.9.4
- npm install -g npm@5.3.0
override:
- script/build --code-sign --compress-artifacts
cache_directories:
- electron
- apm/node_modules
- script/node_modules
- node_modules
- ~/.atom/compile-cache
- ~/.atom/snapshot-cache
test:
override:
- script/lint
- osascript -e 'tell application "System Events" to keystroke "x"' # clear screen saver
- caffeinate -s script/test # Run with caffeinate to prevent screen saver
experimental:
notify:
branches:
only:
- master

View File

@@ -1,8 +1,8 @@
# Atom build status
| System | Travis | AppVeyor/Win | Circle/Mac | Dependencies |
| System | Travis | AppVeyor/Win | VSTS | Dependencies |
|--------|--------|--------------|------------|--------------|
| [Atom](https://github.com/atom/atom) | [![Travis Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) | [![AppVeyor/Wi Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) | [![Circle/Mac Build Status](https://circleci.com/gh/atom/atom.svg?style=shield)](https://circleci.com/gh/atom/atom) | [![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom) |
| [Atom](https://github.com/atom/atom) | [![Travis Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) | [![AppVeyor/Wi Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) | [![Build status](https://github.visualstudio.com/Atom/_apis/build/status/Atom%20Production%20Branches?branch=master)](https://github.visualstudio.com/Atom/_build/latest?definitionId=32&branch=master) | [![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom) |
| [APM](https://github.com/atom/apm) | [![Travis Build Status](https://travis-ci.org/atom/apm.svg?branch=master)](https://travis-ci.org/atom/apm) | [![AppVeyor/Wi Build Status](https://ci.appveyor.com/api/projects/status/j6ixw374a397ugkb/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/apm/branch/master) | | [![Dependency Status](https://david-dm.org/atom/apm.svg)](https://david-dm.org/atom/apm) |
| [Electron](https://github.com/electron/electron) | [![Travis Build Status](https://travis-ci.org/electron/electron.svg?branch=master)](https://travis-ci.org/electron/electron) | [![AppVeyor/Wi Build Status](https://ci.appveyor.com/api/projects/status/kvxe4byi7jcxbe26/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/electron) | | [![Dependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron)

View File

@@ -2,10 +2,6 @@
Want to know what the Atom team is working on and what has our focus over the next few months? You've come to the right place. 🎯
The sections below represent our **near-term roadmap**:
* [Atom Core](#atom-core)
* [Tree-sitter](#tree-sitter)
This roadmap is a [living document](https://en.wikipedia.org/wiki/Living_document): it represents our current plans, but we expect these plans to change from time to time. Follow [this link](https://github.com/atom/atom/blob/4fbad81a7cd2f2e3925d7e920086bc1ebf2fe210/docs/focus/README.md) to see the previous major version of this roadmap.
@@ -13,43 +9,20 @@ You can find our bi-weekly iteration plans by searching for issues with the [`it
---
## Atom Core
### Core package development is streamlined
Everything in Atom is a package. While this adds to its hackability, it is not always the best path forward. Consolidating packages as well as thinking about other ways to decrease friction for contributors will help pay down some of our tech debt in this area. More information regarding planning was provided in [this RFC](https://github.com/atom/atom/blob/master/docs/rfcs/003-consolidate-core-packages.md)
### Enable improvements to built-in packages to be delivered more frequently
- [ ] Merge at least 22 packages in to atom/atom
- [ ] Investigate options for enabling more frequent updates to built-in packages either by shipping Atom more frequently or enabling out-of-band package updates
- [ ] Write and publish an RFC describing the proposed alternatives
- [ ] Implement the approved solution such that updates can start being delivered more frequently in the next few months
### Clarify issue and PR processes to streamline triage and contribution
### Improve Communication and Process
- [ ] Refine process for triaging issues and PRs across Atom org repositories
- [ ] Publish a document that outlines merge requirements for PRs
- [ ] Triage existing/old issues and PRs across our repos weekly to clear out the backlog and get our open issues back to a manageable state
- [ ] Publish a document that outlines merge requirements for community PRs
- [ ] Reactive tickets are incorporated in to 80% of all sprints
- [ ] Automate some aspects of Atom issue and PR triage with Probot, especially around ensuring PRs follow our contribution guidelines
### Streamline the Atom Core release process
### Establish and Measure
- [ ] Implement "Publish" action to publish releases using Atom Release Publisher
- [ ] Complete automation of Linux package publishing
- [ ] Automate generation of draft release notes for new releases
- [ ] Investigate scheduled automation of Atom releases
- [ ] Update Atom release process documentation to reflect new release steps
- [ ] Move to VSTS CI to centralize all OS platform builds on a single service
- [ ] Prototype the use of Electron's new update service to see if it works for our needs
### [Stretch] Enable pre-transpilation of built-in packages to remove compiler dependencies from Atom
- [ ] Investigate approaches for pre-transpilation of Babel and TypeScript code in built-in packages
- [ ] Write an RFC that covers both on-demand transpilation and pre-transpilation for Atom builds
## Tree-sitter
### Finish work on Tree-sitter syntax highlighting, enable it by default
- [ ] Implement parsing on a background thread to ensure responsiveness
- [ ] Add a system for highlighting built-in functions and other things not distinguished in the AST.
- [ ] Add a system for parsing things like escape sequences in regexes, which are not identified in the AST.
- [ ] Document the new grammar format in the flight manual.
- [ ] Add a way of disabling Tree-sitter highlighting on a per-language basis.
- [ ] Enable Tree-sitter highlighting by default for one or more languages.
- [ ] Implement Atom metrics dashboard that can be used to drive future decisions
- [ ] Determine what may be helpful to measure in the future building upon work [already in progress](http://blog.atom.io/2018/06/20/atom-metrics.html)

37
docs/rfcs/000-template.md Normal file
View File

@@ -0,0 +1,37 @@
# Feature title
## Status
Proposed
## Summary
One paragraph explanation of the feature.
## Motivation
Why are we doing this? What use cases does it support? What is the expected outcome?
## Explanation
Explain the proposal as if it was already implemented and you were describing it to an Atom user. That generally means:
- Introducing new named concepts.
- Explaining the feature largely in terms of examples.
- Explaining any changes to existing workflows.
## Drawbacks
Why should we *not* do this?
## Rationale and alternatives
- Why is this approach the best in the space of possible approaches?
- What other approaches have been considered and what is the rationale for not choosing them?
- What is the impact of not doing this?
## Unresolved questions
- What unresolved questions do you expect to resolve through the RFC process before this gets merged?
- What unresolved questions do you expect to resolve through the implementation of this feature before it is released in a new version of Atom?
- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?

View File

@@ -0,0 +1,105 @@
# Updatable Bundled Packages
## Status
Proposed
## Summary
This feature will enable an opt-in subset of bundled Atom packages to be updated with `apm` outside of the Atom release cycle. This will enable users to receive new functionality and bug fixes for some bundled packages as regularly as needed without waiting for them to be included in a new Atom release. This is especially important for packages like [GitHub](https://github.com/atom/github/) and [Teletype](https://github.com/atom/teletype/) which provide essential Atom functionality and could be improved independently of Atom.
## Motivation
Atom currently uses a monthly release cycle with staged Stable and Beta releases so that major issues get caught early in Beta before reaching the Stable release. Because Atom releases updates monthly, this means that a new feature merged into `master` right after a new Atom release could take one month to reach the next Beta and then another month to reach Stable.
Since a large part of Atom's built-in functionality is provided by bundled packages, it makes sense to allow some of those packages to be updated independently of Atom's monthly release cycle so that users can receive new features and fixes whenever they become available.
Bundled packages are treated differently than community packages that you can install using `apm`:
- You are not prompted to update them when new versions are released on `apm`
- `apm` will warn you at the command line when you try to install or update a bundled package
- If a user intentionally installs a bundled package from `apm` the [dalek package](https://github.com/atom/dalek/) will show a warning in the "deprecations" view asking the user to remove the offending package
Despite all this, if the user *does* manually install an update to a bundled package using `apm`, it will be loaded into the editor and updated dutifully as new releases occur. The only new functionality needed is to enable `apm` to check bundled packages for updates when those packages haven't yet been installed in the user's `~/.atom/packages` folder.
The primary use case for this improvement is enabling the GitHub package to ship improvements more frequently than Atom's release cycle since many of its improvements can be done without changes to Atom itself. If this approach is proven to work well for the GitHub package, we might also consider using it to ship Teletype as a bundled Atom package.
## Explanation
Any bundled Atom package can opt in to new updates released via `apm` by adding `"coreUpdatable": true` to its `package.json` file. This causes `apm` to consider it as part of the list of packages it checks for updates. If a community (non-bundled) package sets this field to `true` or `false` it will be ignored as it's only relevant to bundled packages.
Atom shows update notifications for Updatable bundled packages whenever they are available so long as those updates support the engine version of the current Atom build. Bundled package updates can also be found and installed in the Settings view's *Updates* tab.
The `dalek` package is aware of the new "Updatable" metadata and excludes updated bundled packages from its deprecation warnings.
### User Experience Examples
1. The user downloads and installs Atom 1.28.0 which includes GitHub package version 0.15.0. Two weeks later, GitHub package 0.16.0 is released with a few new features. The user is prompted to update to the new version and gets the new features even though Atom 1.29.0 hasn't been released yet.
2. The user downloads and installs Atom 1.28.0, including GitHub package 0.15.0, which was released two weeks prior. Since that release the GitHub package has been updated to version 0.15.1 on `apm`. When the user starts Atom for the first time they are prompted to update the GitHub package.
3. In the future, a user has an old install of Atom 1.28.0 and waits a long time between installing Atom updates. The GitHub package releases version 0.25.0 but the user is not prompted to install it because the GitHub package has set `engines` in `package.json` to restrict to Atom 1.32.0 and above.
### Rules for Updatable Bundled Packages
Any package that opts into this behavior must adhere to these rules:
1. **Each release must ensure that its `engines` field in `package.json` reflects the necessary Atom version for the Atom, Electron, and Node.js APIs used in the package**. This field defines the range of Atom versions in which the package is expected to work. The field should always be set to the lowest possible Atom version that the package supports.
2. **Any new update to a bundled package *must* support current Stable *and* Beta releases**. This enables the user to upgrade the package and continue to use it in side-by-side Stable and Beta installs on their machine. If a package wants to use API features of a newer version of Atom while still supporting older Atom versions, it must do so in a way that is aware of the user's version and adjust itself accordingly.
3. **Atom's `package.json` *must* stay up to date with the latest supported version of the package** in the `master` and Beta release branches. This ensures that the user always gets the latest version of the package in a new release and also benefits from its inclusion in Atom's snapshot.
For rule #3, it will be important to have automation to ensure that current Beta release and `master` are kept up to date with the latest compatible version of any updatable bundled package as it will be difficult for maintainers to do that manually. This could be accomplished by a nightly CI run which is focused explicitly on bumping package dependencies in this manner.
## Drawbacks
### Possible API incompatibility
The primary drawback of this approach is that Updatable bundled packages might exhibit problems on older Atom versions due to missing or changed APIs in Atom, Electron, or Node.js. The solution for these packages is to keep their `engines` field updated appropriately, but there's still a chance that some updates will slip through without the necessary engine version changes. If this does occur and users are affected by it, the solution is to publish a new update which rolls back the package to the functionality of its previous release and then publish another new update with the new functionality restored and the proper `engines` version in place.
### Increased Atom startup time
Another major drawback is that the snapshotted code for the bundled package will no longer be used since a newer version has been installed. This updated version of the package cannot be easily added back into Atom's snapshot so it could cause a noticable drag on Atom's startup time. Some quick measurements with Timecop show a 10x increase in GitHub package load time for bundled (snapshot) vs updated (non-snapshot) package code:
| GitHub Package Code | Load Time |
|----------------------------------|-----------|
| **Bundled** | 52 ms |
| **Updated (first load)** | 5026 ms |
| **Updated (subsequent loads)** | 591 ms |
There was no measurable effect on shell or window startup time, only package load time. It seems that the transpilation phase of the first load of the package incurs a 100x increase in load time. Pre-transpilation of the package code (either when shipped or when installed using `apm`) will be useful in mitigating this cost. Further investigation into snapshotting package code will be needed to understand if the load time increase can be mitigated.
There is a possibility that the GitHub package could load parts of its codebase on demand to mitigate the increased startup time when not loaded as part of Atom's snapshot. This approach is discussed in more detail at [atom/github#1522](https://github.com/atom/github/issues/1522).
### Incompatibility across Atom release channels
One other possible drawback is that an updated version of a bundled package might not be compatible across two different Atom channels. For example, if the user installs a new update to a bundled package that only supports the current Atom Beta release or higher, the user will no longer have access to that package if they open Atom Stable. However, this drawback is no different than what the user would face today installing a community package under the same circumstances, so this could be considered a general problem in the Atom package ecosystem.
Finally, one risk of this approach is that the Atom team forgets to update a bundled package to its latest appropriate version on `apm` just before a new release. If this happens, the user will install a new Atom update and then be prompted to update a package that should have been snapshotted and shipped in-box. To avoid this problem we could add some build automation that checks for the latest version of a bundled package to see if the current Atom build would be supported by it.
## Rationale and alternatives
This is the best approach for updating bundled packages because it allows those packages to take control of their own release cycle so long as they manage their Atom engine version correctly. It also does so in a way that allows us to decide which packages can be updated independently, reducing the likelihood of problems for users.
The primary alternative to this approach is to speed up the Atom release cycle so that bundled Atom package updates will reach users more frequently. This approach will be investigated independently of this RFC as it may still be valuable even with Updatable bundled packages.
## Unresolved questions
> - What unresolved questions do you expect to resolve through the RFC process before this gets merged?
Is it enough to just depend on the `engines` field of `package.json` to protect users from installing a package update that doesn't work with their version of Atom?
> - What unresolved questions do you expect to resolve through the implementation of this feature before it is released in a new version of Atom?
Is there any optimization we can use to reduce the performance hit of loading updated bundled packages?
> - What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?
One issue that's out of scope for this RFC is how we ship new features and fixes to the core components of Atom (not its bundled packages) more frequently. There are two options we can investigate to accomplish this:
- **Ship Atom updates more frequently, possibly every two weeks**
- **Introduce a channel for nightly builds which surface the latest changes every day**
Both of these possibilities will be covered in future RFCs as they could be implemented independently of the feature described in this RFC.

View File

@@ -0,0 +1,57 @@
# Atom Nightly Releases
## Status
Implemented in PR [#17538](https://github.com/atom/atom/pull/17538)
## Summary
This RFC proposes that Atom add a third official release channel which delivers new builds of Atom nightly from the `master` branch. Nightly releases will allow new improvements to reach users long before a new Stable or Beta release is shipped. This effort will also give us the opportunity to experiment with new release automation strategies that could eventually be used to speed up the Stable and Beta release cadence.
## Motivation
Atom currently uses a monthly release cycle with staged Stable and Beta releases so that major issues get caught early in Beta before reaching the Stable release. Because Atom releases updates monthly, this means that a new feature merged into `master` right after a new Atom release could take one month to reach the next Beta and then another month to reach Stable.
This release process works well for delivering stable improvements to users on a regular basis but it results in friction for users who want to try out the latest Atom improvements and provide feedback. If we deliver a nightly release channel, it will be possible to deliver new features and bug fixes on a regular basis and get valuable feedback to guide our work.
Today, a bleeding-edge user must manually pull Atom's `master` branch and compile their own build. There is a source of `dev` builds from `master` across our CI services but those aren't made available to users as an official distribution.
## Explanation
A user who wants to use the latest improvements to Atom each day can go to atom.io, download the Atom Nightly release, and install it on their machine. This release can be installed alongside Atom Stable and Atom Beta.
Each night when there are new commits to Atom's `master` branch, a scheduled CI build creates a new Atom Nightly release with packages for Windows, macOS, and Linux. These packages are automatically uploaded to a new GitHub release on the `atom/atom-nightly-releases` repository using a monotonically-increasing nightly version based off of the version in `master` (e.g. `v1.29.0-nightly1`).
Every 4 hours, an Atom Nightly release installed on Windows or macOS checks for a new update by consulting Electron's [update.electronjs.org](update-electron) service. If a new update is available, it is downloaded in the background and the user is notified to restart Atom once it's complete. This update flow is the same as what users experience in Atom Stable or Beta releases but updates occur more frequently.
Linux users must manually download nightly releases for now as there isn't an easy way to automatically install new updates across the various Linux distributions. We may consider providing updatable [AppImage](http://appimage.org/) packages in the future; this will be proposed in a separate RFC.
## Drawbacks
There isn't a major downside to this effort since it would run in parallel to the existing Atom release process without affecting it.
## Rationale and alternatives
This is a useful approach because it allows us to achieve a much more rapid feedback loop with highly engaged users to ensure that Atom is improving regularly. It's the best approach because it allows us to get rapid feedback without sacrificing the stability of the Stable and Beta releases.
Another option is to speed up Atom's release cadence to ship Stable and Beta every two weeks (or more regularly). This approach could shorten our feedback loop but at the expense of greater instability since new improvements would not have as much time to be polished before release.
The impact of not taking this approach is that we continue to have to wait 1-2 months to get feedback from users about new features or bugs in Stable and Beta releases.
## Unresolved questions
- **What should we call this release channel?**
Some ideas:
- Atom Nightly
- Atom Reactor
- Atom Dev - Currently the name of dev builds but it might make sense to leave that for "normal" builds from `master`
According to a [Twitter poll](https://twitter.com/daviwil/status/1006545552987701248) with about 1,600 responses, 50% of the voters chose "Atom Nightly". The final name will be determined before launch.
- **Will Electron's new autoUpdate service work for all Atom releases?**
One outcome of this effort is to use the new [update.electronjs.org](update-electron) service for Atom's update checks so that we can deprecate on our own custom update service. Building the Nightly channel on this service will allow us to evaluate it to see if it meets the needs of the Stable and Beta channels.
[update-electron]: https://github.com/electron/update.electronjs.org

View File

@@ -0,0 +1,345 @@
# Consolidate Core Atom Packages
## Status
Accepted
## Summary
Atom's official distribution is comprised of 92 core packages which provide its built-in functionality. These packages currently live in their own independent repositories in the Atom organization, all with their own separate issues, PRs, releases, and CI configurations. This RFC proposes that by consolidating most, if not all, of these core packages back into the `atom/atom` repo, we will see the following benefits:
- Less confusion for new contributors
- Simpler core package contribution experience
- Greatly reduced burden for maintainers
## Motivation
Let's cover each of the bullet points mentioned above:
### Less confusion for contributors
Imagine that a new contributor wants to add a small new feature to the `tree-view` package. The first place they are likely to look is the `atom/atom` repository. Scanning through the folders will lead to a dead end as nothing that looks like `tree-view` code can be found. They might take one of the following steps next:
- By reading README.md, maybe they will decide to click the link to the Atom Flight Manual and _maybe_ find the [Contributing to Official Atom Packages](https://flight-manual.atom.io/hacking-atom/sections/contributing-to-official-atom-packages/) page there
- They could read the CONTRIBUTING.md file which [has a section](https://github.com/atom/atom/blob/master/CONTRIBUTING.md#atom-and-packages) that explains where to find the repos for core packages and how to contribute, but we don't really have a clear pointer to that in our README.md
- If they don't happen to find that page, they might use Google to search for "atom tree view" and find the atom/tree-view repo and _maybe_ read the CONTRIBUTING.md file which sends them to Atom's overall contribution documentation
- They might go to the Atom Forum or Slack community to ask how to contribute to a particular part of Atom and *hopefully* get a helpful response that points them in the right direction
Having all of the core Atom packages represented in a top-level `packages` folder, even if they all don't actually live in the repo, will go a long way to making the core package code more discoverable.
### Simpler core package contribution experience
Separating core Atom features out into individual repositories and delivering them to Atom builds via `apm` is a great idea in theory because it validates the Atom package ecosystem and gives developers many examples of how to develop an Atom package. It also gives Atom developers real-world experience working with Atom's APIs so that we ensure community package authors have the same hackability that Atom developers enjoy.
On the other hand, having these packages live in separate repositories and released "independently" introduces a great deal of overhead when adding new features. Here is a comparison of the current package development workflow contrasted to what we could achieve with consolidated packages:
#### Current Package Development Workflow
For example, to add a single feature to the `tree-view` package, one must:
1. Fork and clone the `tree-view` repository to their computer (making sure to pull the commit relevant to the version of Atom they are working with)
1. Run `apm install` and `apm link` inside of the repo folder
1. Make their desired changes to the code
1. Open a PR to the `tree-view` repo and wait for CI to pass and a maintainer to review it
1. Work with maintainers to get the PR approved and merged
After this is finished, an Atom maintainer must take the following steps:
1. Clone the `tree-view` repo
2. Run `apm publish` to publish a new release of the package
3. Edit `package.json` in the Atom repo to reflect the new version of `tree-view`
4. Commit and push the changes to the relevant branch where the change belongs (`master` or `1.nn-releases`)
#### Simplified Package Development
If we were to move `tree-view` (or any other core Atom package) back into `atom/atom`, the development workflow would look more like this:
1. Fork and clone `atom/atom` and switch to a release branch if necessary
1. Build Atom and launch it in dev mode
1. Make desired changes to the code in `packages/tree-view`
1. Open a PR on `atom/atom` and wait for CI to pass and a maintainer to review it
1. Work with maintainers to get the PR approved and merged
At this point, the change is merged into Atom and ready for inclusion in the next release.
### Greatly reduced burden for maintainers
Since packages all have their own repositories, this means that we have to watch 91 different repos for issues and pull requests. This also means that we have to redirect issues filed on `atom/atom` to the appropriate repository when a user doesn't know where it belongs. Even more importantly, there's not an easy way to prioritize and track issues across the Atom organization without using GitHub Projects.
Also, as mentioned above, there's the added duty of doing the package "version dance" when we merge any new PRs to a package repository: publish the package update, update `package.json` in Atom. It's very easy to forget to do this and not have community contributions included in the next Atom release!
The more core packages live in `atom/atom`, the less work Atom maintainers have to do overall.
## Explanation
Many of Atom's core packages now live in the core `atom/atom` repository. To the Atom user, this change will be imperceptible as these packages still show up in the list of Core Packages in the Settings View. Users can still optionally disable these packages.
For maintainers and contributors, there will be less juggling of repositories and no more publishing of updates to these packages with `apm`:
Contributors now clone and build `atom/atom` to work on improvements to core packages. They will no longer have to use `apm link` in dev mode to test changes they make to packages in the repo's `packages` folder. Core packages that aren't consolidated still have folders under `packages` with README.md files that point to the home repository for that package.
When a contributor sends a PR to `atom/atom` that only affects files in a folder under `packages`, only the specs for the relevant package folders will be executed using Atom's CI scripts. This means that a full Atom build will not be required when no Atom Core code is changed in a PR. Package specs are also now run against all 3 OSes on Atom `master` and release builds.
Atom maintainers no longer have to publish new versions to consolidated core packages and then edit `package.json` to bump the package version in a particular Atom release branch (Stable, Beta, or `master`). When a PR against a consolidated core package in `atom/atom` is merged, no version number change is required and the changes will immediately be a part of the next release from that branch.
## Drawbacks
One possible drawback of this approach is that there might be some initial confusion where core Atom packages live, especially if some are consolidated into `atom/atom` and others still live in their own repositories. We will manage this confusion by doing the following:
- Include a `README.md` file in the `packages` folder which lists core packages that are not consolidated in the Atom repo. This will enable users to find the home repositories of those packages.
- Archive the repositories for consolidated core packages, but only after migrating existing issues, merging or closing existing PRs, and updating the README.md to point to the new home of the package code.
Also, contributors will now have to fork, clone, and build `atom/atom` to contribute to core packages where they would previously just need to clone the package repository. This might put added burden on them such as installing necessary build dependencies on their machine that they wouldn't otherwise need. It is very likely we could simplify this process for them, though.
One final drawback is that it will now be harder to have single-package maintainers. We currently have 7 core packages where there is a maintainer who isn't a part of the core Atom maintainers team. These maintainers generally are able to merge community PRs and make commits to those packages with their own judgement. If we get rid of individual package repositories, do we now make those maintainers full Atom maintainers?
## Rationale and alternatives
The Motivation section explains most of the rationale, so this section will focus on the process of consolidating packages back into `atom/atom`. The set of packages we've chosen to consolidate were evaluated based on a few factors:
- Number of open issues and PRs (exclude any with > 10 open PRs)
- Time since last update (longer duration since last update is prioritized)
- Number of package-only maintainers on the repo (exclude any with package maintainers for now)
Using this criteria, all 91 packages have been evaluated and categorized to determine whether they are good candidates for consolidation:
#### Initial Consolidation Candidates
| Package | Open Issues | Open PRs | Outside Maintainers | Last Updated |
|---------|-------------|----------|---------------------| -------------|
| **[about]** | 2 | 0 | 0 | 7/11/18 |
| **[archive-view]** | 10 | 0 | 0 | 6/3/18 |
| **[atom-dark-syntax]** | 5 | 0 | 0 | 12/6/17 |
| **[atom-dark-ui]** | 1 | 2 | 0 | 2/13/18 |
| **[atom-light-syntax]** | 1 | 0 | 0 | 10/17/16 |
| **[atom-light-ui]** | 1 | 0 | 0 | 2/13/18 |
| **[autoflow]** | 17 | 4 | 0 | 4/17/18 |
| **[autosave]** | 13 | 0 | 0 | 9/16/17 |
| **[background-tips]** | 3 | 2 | 0 | 2/17/18 |
| **[base16-tomorrow-dark-theme]** | 5 | 0 | 0 | 1/10/17 |
| **[base16-tomorrow-light-theme]** | 1 | 0 | 0 | 1/10/17 |
| **[bookmarks]** | 19 | 4 | 0 | 12/10/17 |
| **[bracket-matcher]** | 74 | 8 | 0 | 3/20/18 |
| **[command-palette]** | 18 | 6 | 0 | 2/27/18 |
| **[dalek]** | 2 | 0 | 0 | 2/28/18 |
| **[deprecation-cop]** | 5 | 0 | 0 | 9/7/17 |
| **[dev-live-reload]** | 4 | 0 | 0 | 11/14/17 |
| **[encoding-selector]** | 11 | 2 | 0 | 4/19/18 |
| **[exception-reporting]** | 5 | 0 | 0 | 2/6/18 |
| **[git-diff]** | 38 | 1 | 0 | 1/18/18 |
| **[go-to-line]** | 5 | 2 | 0 | 1/25/18 |
| **[grammar-selector]** | 3 | 1 | 0 | 4/12/18 |
| **[image-view]** | 4 | 4 | 0 | 7/9/18 |
| **[incompatible-packages]** | 1 | 0 | 0 | 4/25/17 |
| **[keybinding-resolver]** | 11 | 3 | 0 | 7/6/18 |
| **[language-clojure]** | 13 | 3 | 0 | 1/26/18 |
| **[language-coffee-script]** | 9 | 2 | 0 | 11/1/17 |
| **[language-csharp]** | 1 | 1 | 0 | 4/27/18 |
| **[language-css]** | 6 | 7 | 0 | 6/11/18 |
| **[language-gfm]** | 52 | 9 | 0 | 6/15/18 |
| **[language-git]** | 4 | 2 | 0 | 4/18/17 |
| **[language-html]** | 11 | 4 | 0 | 7/5/18 |
| **[language-hyperlink]** | 2 | 3 | 0 | 10/25/17 |
| **[language-json]** | 1 | 0 | 0 | 5/11/18 |
| **[language-less]** | 5 | 1 | 0 | 6/11/18 |
| **[language-make]** | 7 | 3 | 0 | 11/26/16 |
| **[language-mustache]** | 0 | 0 | 0 | 2/5/18 |
| **[language-objective-c]** | 2 | 0 | 0 | 12/1/15 |
| **[language-php]** | 25 | 7 | 0 | 6/11/18 |
| **[language-property-list]** | 1 | 0 | 0 | 3/11/17 |
| **[language-python]** | 33 | 4 | 0 | 6/18/18 |
| **[language-ruby]** | 38 | 10 | 0 | 10/25/17 |
| **[language-ruby-on-rails]** | 9 | 6 | 0 | 12/7/17 |
| **[language-sass]** | 12 | 5 | 0 | 5/2/18 |
| **[language-shellscript]** | 12 | 3 | 0 | 6/18/18 |
| **[language-source]** | 0 | 0 | 0 | 1/6/15 |
| **[language-sql]** | 6 | 4 | 0 | 1/26/18 |
| **[language-text]** | 1 | 0 | 0 | 3/9/18 |
| **[language-todo]** | 10 | 6 | 0 | 1/26/18 |
| **[language-toml]** | 1 | 0 | 0 | 1/6/18 |
| **[language-typescript]** | 6 | 0 | 0 | 6/18/18 |
| **[language-xml]** | 2 | 1 | 0 | 6/12/17 |
| **[language-yaml]** | 8 | 2 | 0 | 3/9/18 |
| **[line-ending-selector]** | 10 | 0 | 0 | 5/18/18 |
| **[link]** | 0 | 1 | 0 | 11/14/17 |
| **[metrics]** | 1 | 2 | 0 | 7/5/18 |
| **[notifications]** | 29 | 8 | 0 | 3/22/18 |
| **[one-dark-syntax]** | 4 | 0 | 0 | 5/27/18 |
| **[one-dark-ui]** | 13 | 1 | 0 | 5/1/18 |
| **[one-light-syntax]** | 2 | 1 | 0 | 5/27/18 |
| **[one-light-ui]** | 2 | 0 | 0 | 5/1/18 |
| **[open-on-github]** | 8 | 3 | 0 | 11/21/17 |
| **[package-generator]** | 10 | 2 | 0 | 11/16/17 |
| **[status-bar]** | 25 | 3 | 0 | 11/6/17 |
| **[styleguide]** | 12 | 2 | 0 | 4/12/18 |
| **[tabs]** | 66 | 7 | 0 | 5/13/18 |
| **[timecop]** | 5 | 0 | 0 | 11/4/17 |
| **[update-package-dependencies]** | 0 | 0 | 0 | 12/10/17 |
| **[welcome]** | 0 | 0 | 0 | 11/21/17 |
| **[whitespace]** | 31 | 6 | 0 | 5/30/18 |
| **[wrap-guide]** | 3 | 4 | 0 | 11/27/17 |
#### Packages to be Consolidated Later
The following packages will not be consolidated until the stated reasons can be resolved or we decide on a consolidation strategy for them:
| Package | Open Issues | Open PRs | Outside Maintainers | Last Updated | Reason |
|---------|-------------|----------|---------------------|--------------|-------|
| **[find-and-replace]** | 219 | 17 | 0 | 6/4/18 | Too many open PRs |
| **[fuzzy-finder]** | 89 | 22 | 0 | 5/17/18 | Too many open PRs |
| **[github]** | | | | | Independent project |
| **[language-c]** | 53 | 15 | 0 | 7/10/18 | Too many open PRs |
| **[language-go]** | 12 | 2 | **1** | 6/18/18 | Package maintainer, possibly inactive? |
| **[language-java]** | 8 | 2 | **1** | 6/11/18 | Package maintainer |
| **[language-javascript]** | 66 | 12 | 0 | 7/6/18 | Too many open PRs |
| **[language-perl]** | 17 | 1 | **1** | 10/30/17 | Package maintainer, possibly inactive? |
| **[markdown-preview]** | 139 | 12 | 0 | 1/8/18 | Too many open PRs |
| **[settings-view]** | 137 | 18 | 0 | 5/17/18 | Too many open PRs |
| **[snippets]** | 57 | 4 | **1** | 4/17/18 | Package maintainer |
| **[solarized-dark-syntax]** | 8 | 3 | **1** | 5/27/18 | Package maintainer |
| **[solarized-light-syntax]** | 2 | 3 | **1** | 5/27/18 | Package maintainer |
| **[spell-check]** | 68 | 14 | **1** | 5/25/18 | Too many open PRs, package maintainer |
| **[symbols-view]** | 86 | 13 | 0 | 12/10/17 | Too many open PRs |
| **[tree-view]** | 210 | 36 | 0 | 3/21/18 | Too many open PRs |
#### Packages to Never Consolidate
These packages will not be consolidated because they would inhibit contributions from our friends in the Nuclide team at Facebook:
- **[autocomplete-atom-api]**
- **[autocomplete-css]**
- **[autocomplete-html]**
- **[autocomplete-plus]**
- **[autocomplete-snippets]**
### Consolidation Process
To consolidate a single core package repository back into `atom/atom`, the following steps will be taken:
1. All open pull requests on the package's repository must either be closed or merged before consolidation can proceed
1. The package repository's code in `master` will be copied over to Atom's `packages` folder in a subfolder bearing that package's name.
1. Atom's `package.json` file will be updated to change the package's `packageDependencies` entry to reference its local path with the following syntax: `"tree-view": "file:./packages/tree-view"`
1. A test build will be created locally to manually verify that the package loads and works correctly at first glance
1. The package specs for the newly-consolidated package will be run against the local Atom build
1. A PR will be sent to `atom/atom` to verify that CI passes with the introduction of the consolidated package
1. Once CI is clean and the PR is approved, the PR will be merged
1. The package's original repository will have all of its existing issues moved over to `atom/atom` using a bulk issue mover tool, assigning a label to those issues relative to the package name, like `packages/tree-view`
1. The package's original repository will have its README.md updated to point contributors to the code's new home in `atom/atom`
1. The package's original repository will now be archived on GitHub
### Alternative Approaches
One alternative approach would be to break this core Atom functionality out of packages and put it directly in the Atom codebase without treating them as packages. This would simplify the development process even further but with the following drawbacks:
- The Atom team would have less regular exposure to Atom package development
- Users would no longer be able to disable core packages to replace their behavior with other packages (different tree views, etc)
## Unresolved questions
- Is there a good reason to not move the `language-*` packages into `atom/atom`?
One concern here is that there exist projects which depend directly on these repositories for the TextMate syntax grammars they contain. Moving the code into `atom/atom` would require that we notify the consumers of the grammars so that they can redirect their requests to the `atom/atom` repo.
- Should we use `git subtree` to migrate the entire commit history of these packages over or just depend on the history from a package's original repository?
For now, we won't use `git subtree` due to the possibility that bringing over thousands of commits could cause unknown problems in the Atom repo. We may try this for newly consolidated packages in the future if we decide that not having the package commit history is a sufficient impediment to problem investigations.
- What are the criteria we might use to eventually decide to move larger packages like `tree-view`, `settings-view`, and `find-and-replace` back into `atom/atom`?
- Will we be losing any useful data about these packages if we don't have standalone repositories anymore?
- Should we use this as an opportunity to remove any unnecessary packages from the core Atom distribution?
[about]: https://github.com/atom/about
[archive-view]: https://github.com/atom/archive-view
[atom-dark-syntax]: https://github.com/atom/atom-dark-syntax
[atom-dark-ui]: https://github.com/atom/atom-dark-ui
[atom-light-syntax]: https://github.com/atom/atom-light-syntax
[atom-light-ui]: https://github.com/atom/atom-light-ui
[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
[autoflow]: https://github.com/atom/autoflow
[autosave]: https://github.com/atom/autosave
[background-tips]: https://github.com/atom/background-tips
[base16-tomorrow-dark-theme]: https://github.com/atom/base16-tomorrow-dark-theme
[base16-tomorrow-light-theme]: https://github.com/atom/base16-tomorrow-light-theme
[bookmarks]: https://github.com/atom/bookmarks
[bracket-matcher]: https://github.com/atom/bracket-matcher
[command-palette]: https://github.com/atom/command-palette
[dalek]: https://github.com/atom/dalek
[deprecation-cop]: https://github.com/atom/deprecation-cop
[dev-live-reload]: https://github.com/atom/dev-live-reload
[encoding-selector]: https://github.com/atom/encoding-selector
[exception-reporting]: https://github.com/atom/exception-reporting
[find-and-replace]: https://github.com/atom/find-and-replace
[fuzzy-finder]: https://github.com/atom/fuzzy-finder
[git-diff]: https://github.com/atom/git-diff
[github]: https://github.com/atom/github
[go-to-line]: https://github.com/atom/go-to-line
[grammar-selector]: https://github.com/atom/grammar-selector
[image-view]: https://github.com/atom/image-view
[incompatible-packages]: https://github.com/atom/incompatible-packages
[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
[line-ending-selector]: https://github.com/atom/line-ending-selector
[link]: https://github.com/atom/link
[markdown-preview]: https://github.com/atom/markdown-preview
[metrics]: https://github.com/atom/metrics
[notifications]: https://github.com/atom/notifications
[one-dark-syntax]: https://github.com/atom/one-dark-syntax
[one-dark-ui]: https://github.com/atom/one-dark-ui
[one-light-syntax]: https://github.com/atom/one-light-syntax
[one-light-ui]: https://github.com/atom/one-light-ui
[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
[solarized-dark-syntax]: https://github.com/atom/solarized-dark-syntax
[solarized-light-syntax]: https://github.com/atom/solarized-light-syntax
[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
[update-package-dependencies]: https://github.com/atom/update-package-dependencies
[welcome]: https://github.com/atom/welcome
[whitespace]: https://github.com/atom/whitespace
[wrap-guide]: https://github.com/atom/wrap-guide

View File

@@ -79,8 +79,8 @@
'ctrl-shift-tab ^ctrl': 'pane:move-active-item-to-top-of-stack'
'cmd-=': 'window:increase-font-size'
'cmd-+': 'window:increase-font-size'
'cmd--': 'window:decrease-font-size'
'cmd-_': 'window:decrease-font-size'
'cmd--': 'window:decrease-font-size'
'cmd-0': 'window:reset-font-size'
'cmd-k up': 'pane:split-up-and-copy-active-item' # Atom Specific

5995
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "atom",
"productName": "Atom",
"version": "1.29.0-dev",
"version": "1.32.0-dev",
"description": "A hackable text editor for the 21st Century.",
"main": "./src/main-process/main.js",
"repository": {
@@ -12,51 +12,128 @@
"url": "https://github.com/atom/atom/issues"
},
"license": "MIT",
"electronVersion": "2.0.1",
"electronVersion": "2.0.7",
"dependencies": {
"@atom/nsfw": "^1.0.18",
"@atom/watcher": "1.0.3",
"@atom/source-map-support": "^0.3.4",
"@atom/watcher": "1.0.8",
"about": "file:packages/about",
"archive-view": "https://www.atom.io/api/packages/archive-view/versions/0.65.1/tarball",
"async": "0.2.6",
"atom-dark-syntax": "https://www.atom.io/api/packages/atom-dark-syntax/versions/0.29.1/tarball",
"atom-dark-ui": "https://www.atom.io/api/packages/atom-dark-ui/versions/0.53.3/tarball",
"atom-keymap": "8.2.10",
"atom-select-list": "^0.7.0",
"atom-light-syntax": "https://www.atom.io/api/packages/atom-light-syntax/versions/0.29.1/tarball",
"atom-light-ui": "https://www.atom.io/api/packages/atom-light-ui/versions/0.46.3/tarball",
"atom-select-list": "^0.7.2",
"atom-ui": "0.4.1",
"autocomplete-atom-api": "https://www.atom.io/api/packages/autocomplete-atom-api/versions/0.10.7/tarball",
"autocomplete-css": "https://www.atom.io/api/packages/autocomplete-css/versions/0.17.5/tarball",
"autocomplete-html": "https://www.atom.io/api/packages/autocomplete-html/versions/0.8.6/tarball",
"autocomplete-plus": "https://www.atom.io/api/packages/autocomplete-plus/versions/2.41.0/tarball",
"autocomplete-snippets": "https://www.atom.io/api/packages/autocomplete-snippets/versions/1.12.0/tarball",
"autoflow": "https://www.atom.io/api/packages/autoflow/versions/0.29.4/tarball",
"autosave": "https://www.atom.io/api/packages/autosave/versions/0.24.6/tarball",
"babel-core": "5.8.38",
"background-tips": "https://www.atom.io/api/packages/background-tips/versions/0.28.0/tarball",
"base16-tomorrow-dark-theme": "https://www.atom.io/api/packages/base16-tomorrow-dark-theme/versions/1.6.0/tarball",
"base16-tomorrow-light-theme": "https://www.atom.io/api/packages/base16-tomorrow-light-theme/versions/1.6.0/tarball",
"bookmarks": "https://www.atom.io/api/packages/bookmarks/versions/0.45.1/tarball",
"bracket-matcher": "https://www.atom.io/api/packages/bracket-matcher/versions/0.89.3/tarball",
"cached-run-in-this-context": "0.4.1",
"chai": "3.5.0",
"chart.js": "^2.3.0",
"clear-cut": "^2.0.2",
"coffee-script": "1.12.7",
"color": "^0.7.3",
"command-palette": "https://www.atom.io/api/packages/command-palette/versions/0.43.5/tarball",
"dalek": "https://www.atom.io/api/packages/dalek/versions/0.2.2/tarball",
"dedent": "^0.7.0",
"deprecation-cop": "https://www.atom.io/api/packages/deprecation-cop/versions/0.56.9/tarball",
"dev-live-reload": "https://www.atom.io/api/packages/dev-live-reload/versions/0.48.1/tarball",
"devtron": "1.3.0",
"encoding-selector": "https://www.atom.io/api/packages/encoding-selector/versions/0.23.9/tarball",
"etch": "^0.12.6",
"event-kit": "^2.5.0",
"exception-reporting": "https://www.atom.io/api/packages/exception-reporting/versions/0.43.1/tarball",
"find-and-replace": "https://www.atom.io/api/packages/find-and-replace/versions/0.215.14/tarball",
"find-parent-dir": "^0.3.0",
"first-mate": "7.1.1",
"focus-trap": "^2.3.0",
"focus-trap": "2.4.5",
"fs-admin": "^0.1.6",
"fs-plus": "^3.0.1",
"fstream": "0.1.24",
"fuzzaldrin": "^2.1",
"git-utils": "5.4.0",
"fuzzy-finder": "https://www.atom.io/api/packages/fuzzy-finder/versions/1.8.2/tarball",
"git-diff": "https://www.atom.io/api/packages/git-diff/versions/1.3.9/tarball",
"git-utils": "5.2.1",
"github": "https://www.atom.io/api/packages/github/versions/0.19.0/tarball",
"glob": "^7.1.1",
"go-to-line": "https://www.atom.io/api/packages/go-to-line/versions/0.33.0/tarball",
"grammar-selector": "https://www.atom.io/api/packages/grammar-selector/versions/0.50.1/tarball",
"grim": "1.5.0",
"image-view": "https://www.atom.io/api/packages/image-view/versions/0.63.1/tarball",
"incompatible-packages": "https://www.atom.io/api/packages/incompatible-packages/versions/0.27.3/tarball",
"jasmine-json": "~0.0",
"jasmine-reporters": "1.1.0",
"jasmine-tagged": "^1.1.4",
"key-path-helpers": "^0.4.0",
"keybinding-resolver": "https://www.atom.io/api/packages/keybinding-resolver/versions/0.38.3/tarball",
"language-c": "https://www.atom.io/api/packages/language-c/versions/0.60.5/tarball",
"language-clojure": "https://www.atom.io/api/packages/language-clojure/versions/0.22.7/tarball",
"language-coffee-script": "https://www.atom.io/api/packages/language-coffee-script/versions/0.49.3/tarball",
"language-csharp": "https://www.atom.io/api/packages/language-csharp/versions/1.1.0/tarball",
"language-css": "https://www.atom.io/api/packages/language-css/versions/0.42.11/tarball",
"language-gfm": "https://www.atom.io/api/packages/language-gfm/versions/0.90.5/tarball",
"language-git": "https://www.atom.io/api/packages/language-git/versions/0.19.1/tarball",
"language-go": "https://www.atom.io/api/packages/language-go/versions/0.46.3/tarball",
"language-html": "https://www.atom.io/api/packages/language-html/versions/0.51.5/tarball",
"language-hyperlink": "https://www.atom.io/api/packages/language-hyperlink/versions/0.16.3/tarball",
"language-java": "https://www.atom.io/api/packages/language-java/versions/0.30.0/tarball",
"language-javascript": "https://www.atom.io/api/packages/language-javascript/versions/0.129.9/tarball",
"language-json": "https://www.atom.io/api/packages/language-json/versions/0.19.2/tarball",
"language-less": "https://www.atom.io/api/packages/language-less/versions/0.34.2/tarball",
"language-make": "https://www.atom.io/api/packages/language-make/versions/0.22.3/tarball",
"language-mustache": "https://www.atom.io/api/packages/language-mustache/versions/0.14.5/tarball",
"language-objective-c": "https://www.atom.io/api/packages/language-objective-c/versions/0.15.1/tarball",
"language-perl": "https://www.atom.io/api/packages/language-perl/versions/0.38.1/tarball",
"language-php": "https://www.atom.io/api/packages/language-php/versions/0.44.0/tarball",
"language-property-list": "https://www.atom.io/api/packages/language-property-list/versions/0.9.1/tarball",
"language-python": "https://www.atom.io/api/packages/language-python/versions/0.51.5/tarball",
"language-ruby": "https://www.atom.io/api/packages/language-ruby/versions/0.72.7/tarball",
"language-ruby-on-rails": "https://www.atom.io/api/packages/language-ruby-on-rails/versions/0.25.3/tarball",
"language-sass": "https://www.atom.io/api/packages/language-sass/versions/0.62.0/tarball",
"language-shellscript": "https://www.atom.io/api/packages/language-shellscript/versions/0.27.5/tarball",
"language-source": "https://www.atom.io/api/packages/language-source/versions/0.9.0/tarball",
"language-sql": "https://www.atom.io/api/packages/language-sql/versions/0.25.10/tarball",
"language-text": "https://www.atom.io/api/packages/language-text/versions/0.7.4/tarball",
"language-todo": "https://www.atom.io/api/packages/language-todo/versions/0.29.4/tarball",
"language-toml": "https://www.atom.io/api/packages/language-toml/versions/0.18.2/tarball",
"language-typescript": "https://www.atom.io/api/packages/language-typescript/versions/0.4.6/tarball",
"language-xml": "https://www.atom.io/api/packages/language-xml/versions/0.35.2/tarball",
"language-yaml": "https://www.atom.io/api/packages/language-yaml/versions/0.32.0/tarball",
"less-cache": "1.1.0",
"line-ending-selector": "https://www.atom.io/api/packages/line-ending-selector/versions/0.7.7/tarball",
"line-top-index": "0.3.1",
"link": "https://www.atom.io/api/packages/link/versions/0.31.6/tarball",
"markdown-preview": "https://www.atom.io/api/packages/markdown-preview/versions/0.159.24/tarball",
"marked": "^0.3.12",
"metrics": "https://www.atom.io/api/packages/metrics/versions/1.6.2/tarball",
"minimatch": "^3.0.3",
"mocha": "2.5.1",
"mocha-junit-reporter": "^1.13.0",
"mocha-multi-reporters": "^1.1.4",
"mock-spawn": "^0.2.6",
"normalize-package-data": "^2.0.0",
"notifications": "https://www.atom.io/api/packages/notifications/versions/0.70.5/tarball",
"nslog": "^3",
"one-dark-syntax": "file:packages/one-dark-syntax",
"one-dark-ui": "https://www.atom.io/api/packages/one-dark-ui/versions/1.12.5/tarball",
"one-light-syntax": "https://www.atom.io/api/packages/one-light-syntax/versions/1.8.4/tarball",
"one-light-ui": "file:packages/one-light-ui",
"oniguruma": "6.2.1",
"open-on-github": "https://www.atom.io/api/packages/open-on-github/versions/1.3.1/tarball",
"package-generator": "https://www.atom.io/api/packages/package-generator/versions/1.3.0/tarball",
"pathwatcher": "8.0.1",
"postcss": "5.2.4",
"postcss-selector-parser": "2.2.1",
@@ -69,87 +146,102 @@
"season": "^6.0.2",
"semver": "^4.3.3",
"service-hub": "^0.7.4",
"settings-view": "https://www.atom.io/api/packages/settings-view/versions/0.256.0/tarball",
"sinon": "1.17.4",
"snippets": "https://www.atom.io/api/packages/snippets/versions/1.3.5/tarball",
"solarized-dark-syntax": "https://www.atom.io/api/packages/solarized-dark-syntax/versions/1.2.0/tarball",
"solarized-light-syntax": "https://www.atom.io/api/packages/solarized-light-syntax/versions/1.2.0/tarball",
"spell-check": "https://www.atom.io/api/packages/spell-check/versions/0.74.1/tarball",
"status-bar": "https://www.atom.io/api/packages/status-bar/versions/1.8.15/tarball",
"styleguide": "https://www.atom.io/api/packages/styleguide/versions/0.49.12/tarball",
"symbols-view": "https://www.atom.io/api/packages/symbols-view/versions/0.118.2/tarball",
"tabs": "https://www.atom.io/api/packages/tabs/versions/0.109.2/tarball",
"temp": "^0.8.3",
"text-buffer": "13.14.3",
"tree-sitter": "0.12.8",
"text-buffer": "13.14.8",
"timecop": "https://www.atom.io/api/packages/timecop/versions/0.36.2/tarball",
"tree-sitter": "0.13.9",
"tree-view": "https://www.atom.io/api/packages/tree-view/versions/0.224.2/tarball",
"typescript-simple": "1.0.0",
"underscore-plus": "^1.6.8",
"update-package-dependencies": "https://www.atom.io/api/packages/update-package-dependencies/versions/0.13.1/tarball",
"welcome": "https://www.atom.io/api/packages/welcome/versions/0.36.7/tarball",
"whitespace": "https://www.atom.io/api/packages/whitespace/versions/0.37.6/tarball",
"winreg": "^1.2.1",
"wrap-guide": "https://www.atom.io/api/packages/wrap-guide/versions/0.40.3/tarball",
"yargs": "^3.23.0"
},
"packageDependencies": {
"atom-dark-syntax": "0.29.0",
"atom-dark-ui": "0.53.2",
"atom-light-syntax": "0.29.0",
"atom-light-ui": "0.46.2",
"base16-tomorrow-dark-theme": "1.5.0",
"base16-tomorrow-light-theme": "1.5.0",
"one-dark-ui": "1.12.3",
"one-light-ui": "1.12.3",
"one-dark-syntax": "1.8.3",
"one-light-syntax": "1.8.3",
"solarized-dark-syntax": "1.1.5",
"solarized-light-syntax": "1.1.5",
"about": "1.9.1",
"archive-view": "0.65.0",
"atom-dark-syntax": "0.29.1",
"atom-dark-ui": "0.53.3",
"atom-light-syntax": "0.29.1",
"atom-light-ui": "0.46.3",
"base16-tomorrow-dark-theme": "1.6.0",
"base16-tomorrow-light-theme": "1.6.0",
"one-dark-ui": "1.12.5",
"one-light-ui": "file:./packages/one-light-ui",
"one-dark-syntax": "file:./packages/one-dark-syntax",
"one-light-syntax": "1.8.4",
"solarized-dark-syntax": "1.2.0",
"solarized-light-syntax": "1.2.0",
"about": "file:./packages/about",
"archive-view": "0.65.1",
"autocomplete-atom-api": "0.10.7",
"autocomplete-css": "0.17.5",
"autocomplete-html": "0.8.4",
"autocomplete-plus": "2.40.6",
"autocomplete-html": "0.8.6",
"autocomplete-plus": "2.41.0",
"autocomplete-snippets": "1.12.0",
"autoflow": "0.29.4",
"autosave": "0.24.6",
"background-tips": "0.28.0",
"bookmarks": "0.45.1",
"bracket-matcher": "0.89.2",
"bracket-matcher": "0.89.3",
"command-palette": "0.43.5",
"dalek": "0.2.2",
"deprecation-cop": "0.56.9",
"dev-live-reload": "0.48.1",
"encoding-selector": "0.23.9",
"exception-reporting": "0.43.1",
"find-and-replace": "0.215.11",
"find-and-replace": "0.215.14",
"fuzzy-finder": "1.8.2",
"github": "0.16.0",
"github": "0.19.0",
"git-diff": "1.3.9",
"go-to-line": "0.33.0",
"grammar-selector": "0.50.1",
"image-view": "0.62.4",
"image-view": "0.63.1",
"incompatible-packages": "0.27.3",
"keybinding-resolver": "0.38.1",
"keybinding-resolver": "0.38.3",
"line-ending-selector": "0.7.7",
"link": "0.31.4",
"markdown-preview": "0.159.20",
"metrics": "1.2.6",
"link": "0.31.6",
"markdown-preview": "0.159.24",
"metrics": "1.6.2",
"notifications": "0.70.5",
"open-on-github": "1.3.1",
"package-generator": "1.3.0",
"settings-view": "0.255.0",
"snippets": "1.3.3",
"spell-check": "0.73.5",
"settings-view": "0.256.0",
"snippets": "1.3.5",
"spell-check": "0.74.1",
"status-bar": "1.8.15",
"styleguide": "0.49.11",
"styleguide": "0.49.12",
"symbols-view": "0.118.2",
"tabs": "0.109.2",
"timecop": "0.36.2",
"tree-view": "0.222.0",
"tree-view": "0.224.2",
"update-package-dependencies": "0.13.1",
"welcome": "0.36.6",
"welcome": "0.36.7",
"whitespace": "0.37.6",
"wrap-guide": "0.40.3",
"language-c": "0.59.9",
"language-c": "0.60.5",
"language-clojure": "0.22.7",
"language-coffee-script": "0.49.3",
"language-csharp": "1.0.4",
"language-csharp": "1.1.0",
"language-css": "0.42.11",
"language-gfm": "0.90.4",
"language-gfm": "0.90.5",
"language-git": "0.19.1",
"language-go": "0.45.3",
"language-html": "0.50.0",
"language-go": "0.46.3",
"language-html": "0.51.5",
"language-hyperlink": "0.16.3",
"language-java": "0.30.0",
"language-javascript": "0.128.7",
"language-javascript": "0.129.9",
"language-json": "0.19.2",
"language-less": "0.34.2",
"language-make": "0.22.3",
@@ -158,17 +250,17 @@
"language-perl": "0.38.1",
"language-php": "0.44.0",
"language-property-list": "0.9.1",
"language-python": "0.50.0",
"language-ruby": "0.71.4",
"language-python": "0.51.5",
"language-ruby": "0.72.7",
"language-ruby-on-rails": "0.25.3",
"language-sass": "0.62.0",
"language-shellscript": "0.26.5",
"language-shellscript": "0.27.5",
"language-source": "0.9.0",
"language-sql": "0.25.10",
"language-text": "0.7.4",
"language-todo": "0.29.4",
"language-toml": "0.18.2",
"language-typescript": "0.3.3",
"language-typescript": "0.4.6",
"language-xml": "0.35.2",
"language-yaml": "0.32.0"
},

194
packages/README.md Normal file
View File

@@ -0,0 +1,194 @@
# Atom 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.
> **NOTE:** There is an ongoing effort to migrate more Atom 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** | [`./packages/about`](./about) | [#17832](https://github.com/atom/atom/issues/17832) |
| **atom-dark-syntax** | [`atom/atom-dark-syntax`][atom-dark-syntax] | [#17849](https://github.com/atom/atom/issues/17849) |
| **atom-dark-ui** | [`atom/atom-dark-ui`][atom-dark-ui] | [#17850](https://github.com/atom/atom/issues/17850) |
| **atom-light-syntax** | [`atom/atom-light-syntax`][atom-light-syntax] | [#17851](https://github.com/atom/atom/issues/17851) |
| **atom-light-ui** | [`atom/atom-light-ui`][atom-light-ui] | [#17852](https://github.com/atom/atom/issues/17852) |
| **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** | [`atom/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** | [`atom/base16-tomorrow-dark-theme`][base16-tomorrow-dark-theme] | [#17836](https://github.com/atom/atom/issues/17836) |
| **base16-tomorrow-light-theme** | [`atom/base16-tomorrow-light-theme`][base16-tomorrow-light-theme] | [#17837](https://github.com/atom/atom/issues/17837) |
| **bookmarks** | [`atom/bookmarks`][bookmarks] | |
| **bracket-matcher** | [`atom/bracket-matcher`][bracket-matcher] | |
| **command-palette** | [`atom/command-palette`][command-palette] | |
| **dalek** | [`atom/dalek`][dalek] | [#17838](https://github.com/atom/atom/issues/17838) |
| **deprecation-cop** | [`atom/deprecation-cop`][deprecation-cop] | [#17839](https://github.com/atom/atom/issues/17839) |
| **dev-live-reload** | [`atom/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** | [`atom/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** | [`atom/git-diff`][git-diff] | [#17843](https://github.com/atom/atom/issues/17843) |
| **go-to-line** | [`atom/go-to-line`][go-to-line] | [#17844](https://github.com/atom/atom/issues/17844) |
| **grammar-selector** | [`atom/grammar-selector`][grammar-selector] | [#17845](https://github.com/atom/atom/issues/17845) |
| **image-view** | [`atom/image-view`][image-view] | |
| **incompatible-packages** | [`atom/incompatible-packages`][incompatible-packages] | [#17846](https://github.com/atom/atom/issues/17846) |
| **keybinding-resolver** | [`atom/keybinding-resolver`][keybinding-resolver] | |
| **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] | |
| **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** | [`atom/line-ending-selector`][line-ending-selector] | [#17847](https://github.com/atom/atom/issues/17847) |
| **link** | [`atom/link`][link] | [#17848](https://github.com/atom/atom/issues/17848) |
| **markdown-preview** | [`atom/markdown-preview`][markdown-preview] | |
| **metrics** | [`atom/metrics`][metrics] | |
| **notifications** | [`atom/notifications`][notifications] | |
| **one-dark-syntax** | [`./packages/one-dark-syntax`](./one-dark-syntax) | [#17853](https://github.com/atom/atom/issues/17853) |
| **one-dark-ui** | [`atom/one-dark-ui`][one-dark-ui] | [#17854](https://github.com/atom/atom/issues/17854) |
| **one-light-syntax** | [`atom/one-light-syntax`][one-light-syntax] | [#17855](https://github.com/atom/atom/issues/17855) |
| **one-light-ui** | [`./packages/one-light-ui`](./one-light-ui) | [#17856](https://github.com/atom/atom/issues/17856) |
| **open-on-github** | [`atom/open-on-github`][open-on-github] | |
| **package-generator** | [`atom/package-generator`][package-generator] | |
| **settings-view** | [`atom/settings-view`][settings-view] | |
| **snippets** | [`atom/snippets`][snippets] | |
| **solarized-dark-syntax** | [`atom/solarized-dark-syntax`][solarized-dark-syntax] | |
| **solarized-light-syntax** | [`atom/solarized-light-syntax`][solarized-light-syntax] | |
| **spell-check** | [`atom/spell-check`][spell-check] | |
| **status-bar** | [`atom/status-bar`][status-bar] | |
| **styleguide** | [`atom/styleguide`][styleguide] | |
| **symbols-view** | [`atom/symbols-view`][symbols-view] | |
| **tabs** | [`atom/tabs`][tabs] | |
| **timecop** | [`atom/timecop`][timecop] | |
| **tree-view** | [`atom/tree-view`][tree-view] | |
| **update-package-dependencies** | [`atom/update-package-dependencies`][update-package-dependencies] | |
| **welcome** | [`atom/welcome`][welcome] | |
| **whitespace** | [`atom/whitespace`][whitespace] | |
| **wrap-guide** | [`atom/wrap-guide`][wrap-guide] | |
[about]: https://github.com/atom/about
[archive-view]: https://github.com/atom/archive-view
[atom-dark-syntax]: https://github.com/atom/atom-dark-syntax
[atom-dark-ui]: https://github.com/atom/atom-dark-ui
[atom-light-syntax]: https://github.com/atom/atom-light-syntax
[atom-light-ui]: https://github.com/atom/atom-light-ui
[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
[autoflow]: https://github.com/atom/autoflow
[autosave]: https://github.com/atom/autosave
[background-tips]: https://github.com/atom/background-tips
[base16-tomorrow-dark-theme]: https://github.com/atom/base16-tomorrow-dark-theme
[base16-tomorrow-light-theme]: https://github.com/atom/base16-tomorrow-light-theme
[bookmarks]: https://github.com/atom/bookmarks
[bracket-matcher]: https://github.com/atom/bracket-matcher
[command-palette]: https://github.com/atom/command-palette
[dalek]: https://github.com/atom/dalek
[deprecation-cop]: https://github.com/atom/deprecation-cop
[dev-live-reload]: https://github.com/atom/dev-live-reload
[encoding-selector]: https://github.com/atom/encoding-selector
[exception-reporting]: https://github.com/atom/exception-reporting
[find-and-replace]: https://github.com/atom/find-and-replace
[fuzzy-finder]: https://github.com/atom/fuzzy-finder
[git-diff]: https://github.com/atom/git-diff
[github]: https://github.com/atom/github
[go-to-line]: https://github.com/atom/go-to-line
[grammar-selector]: https://github.com/atom/grammar-selector
[image-view]: https://github.com/atom/image-view
[incompatible-packages]: https://github.com/atom/incompatible-packages
[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
[line-ending-selector]: https://github.com/atom/line-ending-selector
[link]: https://github.com/atom/link
[markdown-preview]: https://github.com/atom/markdown-preview
[metrics]: https://github.com/atom/metrics
[notifications]: https://github.com/atom/notifications
[one-dark-syntax]: https://github.com/atom/one-dark-syntax
[one-dark-ui]: https://github.com/atom/one-dark-ui
[one-light-syntax]: https://github.com/atom/one-light-syntax
[one-light-ui]: https://github.com/atom/one-light-ui
[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
[solarized-dark-syntax]: https://github.com/atom/solarized-dark-syntax
[solarized-light-syntax]: https://github.com/atom/solarized-light-syntax
[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
[update-package-dependencies]: https://github.com/atom/update-package-dependencies
[welcome]: https://github.com/atom/welcome
[whitespace]: https://github.com/atom/whitespace
[wrap-guide]: https://github.com/atom/wrap-guide

3
packages/about/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.DS_Store
npm-debug.log
node_modules

20
packages/about/LICENSE.md Normal file
View File

@@ -0,0 +1,20 @@
Copyright (c) 2015 Machisté N. Quintana
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.

21
packages/about/README.md Normal file
View File

@@ -0,0 +1,21 @@
# About package
View useful information about your Atom installation.
![About Atom](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.
## 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.
## 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)
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.

View File

@@ -0,0 +1,93 @@
const {CompositeDisposable, Emitter} = require('atom')
const AboutView = require('./components/about-view')
// Deferred requires
let shell
module.exports = class About {
constructor (initialState) {
this.subscriptions = new CompositeDisposable()
this.emitter = new Emitter()
this.state = initialState
this.views = {
aboutView: null
}
this.subscriptions.add(atom.workspace.addOpener((uriToOpen) => {
if (uriToOpen === this.state.uri) {
return this.deserialize()
}
}))
this.subscriptions.add(atom.commands.add('atom-workspace', 'about:view-release-notes', () => {
shell = shell || require('electron').shell
shell.openExternal(this.state.updateManager.getReleaseNotesURLForCurrentVersion())
}))
}
destroy () {
if (this.views.aboutView) this.views.aboutView.destroy()
this.views.aboutView = null
if (this.state.updateManager) this.state.updateManager.dispose()
this.setState({updateManager: null})
this.subscriptions.dispose()
}
setState (newState) {
if (newState && typeof newState === 'object') {
let {state} = this
this.state = Object.assign({}, state, newState)
this.didChange()
}
}
didChange () {
this.emitter.emit('did-change')
}
onDidChange (callback) {
this.emitter.on('did-change', callback)
}
deserialize (state) {
if (!this.views.aboutView) {
this.setState(state)
this.views.aboutView = new AboutView({
uri: this.state.uri,
updateManager: this.state.updateManager,
currentAtomVersion: this.state.currentAtomVersion,
currentElectronVersion: this.state.currentElectronVersion,
currentChromeVersion: this.state.currentChromeVersion,
currentNodeVersion: this.state.currentNodeVersion,
availableVersion: this.state.updateManager.getAvailableVersion()
})
this.handleStateChanges()
}
return this.views.aboutView
}
handleStateChanges () {
this.onDidChange(() => {
if (this.views.aboutView) {
this.views.aboutView.update({
updateManager: this.state.updateManager,
currentAtomVersion: this.state.currentAtomVersion,
currentElectronVersion: this.state.currentElectronVersion,
currentChromeVersion: this.state.currentChromeVersion,
currentNodeVersion: this.state.currentNodeVersion,
availableVersion: this.state.updateManager.getAvailableVersion()
})
}
})
this.state.updateManager.onDidChange(() => {
this.didChange()
})
}
}

View File

@@ -0,0 +1,30 @@
const {CompositeDisposable} = require('atom')
const etch = require('etch')
const EtchComponent = require('../etch-component')
const $ = etch.dom
module.exports =
class AboutStatusBar extends EtchComponent {
constructor () {
super()
this.subscriptions = new CompositeDisposable()
this.subscriptions.add(atom.tooltips.add(this.element, {title: 'An update will be installed the next time Atom is relaunched.<br/><br/>Click the squirrel icon for more information.'}))
}
handleClick () {
atom.workspace.open('atom://about')
}
render () {
return $.div({className: 'about-release-notes inline-block', onclick: this.handleClick.bind(this)},
$.span({type: 'button', className: 'icon icon-squirrel'})
)
}
destroy () {
super.destroy()
this.subscriptions.dispose()
}
}

View File

@@ -0,0 +1,159 @@
const {Disposable} = require('atom')
const etch = require('etch')
const shell = require('shell')
const AtomLogo = require('./atom-logo')
const EtchComponent = require('../etch-component')
const UpdateView = require('./update-view')
const $ = etch.dom
module.exports =
class AboutView extends EtchComponent {
handleAtomVersionClick (e) {
e.preventDefault()
atom.clipboard.write(this.props.currentAtomVersion)
}
handleElectronVersionClick (e) {
e.preventDefault()
atom.clipboard.write(this.props.currentElectronVersion)
}
handleChromeVersionClick (e) {
e.preventDefault()
atom.clipboard.write(this.props.currentChromeVersion)
}
handleNodeVersionClick (e) {
e.preventDefault()
atom.clipboard.write(this.props.currentNodeVersion)
}
handleReleaseNotesClick (e) {
e.preventDefault()
shell.openExternal(this.props.updateManager.getReleaseNotesURLForAvailableVersion())
}
handleLicenseClick (e) {
e.preventDefault()
atom.commands.dispatch(atom.views.getView(atom.workspace), 'application:open-license')
}
handleTermsOfUseClick (e) {
e.preventDefault()
shell.openExternal('https://atom.io/terms')
}
handleHowToUpdateClick (e) {
e.preventDefault()
shell.openExternal('https://flight-manual.atom.io/getting-started/sections/installing-atom/')
}
handleShowMoreClick (e) {
e.preventDefault()
var showMoreDiv = document.querySelector('.show-more')
var showMoreText = document.querySelector('.about-more-expand')
switch (showMoreText.textContent) {
case 'Show more':
showMoreDiv.classList.toggle('hidden')
showMoreText.textContent = 'Hide'
break
case 'Hide':
showMoreDiv.classList.toggle('hidden')
showMoreText.textContent = 'Show more'
break
}
}
render () {
return $.div({className: 'pane-item native-key-bindings about'},
$.div({className: 'about-container'},
$.header({className: 'about-header'},
$.a({className: 'about-atom-io', href: 'https://atom.io'},
$(AtomLogo)
),
$.div({className: 'about-header-info'},
$.span({className: 'about-version-container inline-block atom', onclick: this.handleAtomVersionClick.bind(this)},
$.span({className: 'about-version'}, `${this.props.currentAtomVersion} ${process.arch}`),
$.span({className: 'icon icon-clippy about-copy-version'})
),
$.a({className: 'about-header-release-notes', onclick: this.handleReleaseNotesClick.bind(this)}, 'Release Notes')
),
$.span({className: 'about-version-container inline-block show-more-expand', onclick: this.handleShowMoreClick.bind(this)},
$.span({className: 'about-more-expand'}, 'Show more')
),
$.div({className: 'show-more hidden about-more-info'},
$.div({className: 'about-more-info'},
$.span({className: 'about-version-container inline-block electron', onclick: this.handleElectronVersionClick.bind(this)},
$.span({className: 'about-more-version'}, `Electron: ${this.props.currentElectronVersion} `),
$.span({className: 'icon icon-clippy about-copy-version'})
)
),
$.div({className: 'about-more-info'},
$.span({className: 'about-version-container inline-block chrome', onclick: this.handleChromeVersionClick.bind(this)},
$.span({className: 'about-more-version'}, `Chrome: ${this.props.currentChromeVersion} `),
$.span({className: 'icon icon-clippy about-copy-version'})
)
),
$.div({className: 'about-more-info'},
$.span({className: 'about-version-container inline-block node', onclick: this.handleNodeVersionClick.bind(this)},
$.span({className: 'about-more-version'}, `Node: ${this.props.currentNodeVersion} `),
$.span({className: 'icon icon-clippy about-copy-version'})
)
)
)
)
),
$(UpdateView, {
updateManager: this.props.updateManager,
availableVersion: this.props.availableVersion,
viewUpdateReleaseNotes: this.handleReleaseNotesClick.bind(this),
viewUpdateInstructions: this.handleHowToUpdateClick.bind(this)
}),
$.div({className: 'about-actions group-item'},
$.div({className: 'btn-group'},
$.button({className: 'btn view-license', onclick: this.handleLicenseClick.bind(this)}, 'License'),
$.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'}),
$.span({className: 'inline'}, ' with '),
$.span({className: 'icon icon-heart'}),
$.span({className: 'inline'}, ' by '),
$.a({className: 'icon icon-logo-github', href: 'https://github.com'})
),
$.div({className: 'about-credits group-item'},
$.span({className: 'inline'}, 'And the awesome '),
$.a({href: 'https://github.com/atom/atom/contributors'}, 'Atom Community')
)
)
}
serialize () {
return {
deserializer: this.constructor.name,
uri: this.props.uri
}
}
onDidChangeTitle () {
return new Disposable()
}
onDidChangeModified () {
return new Disposable()
}
getTitle () {
return 'About'
}
getIconName () {
return 'info'
}
}

View File

@@ -0,0 +1,28 @@
const etch = require('etch')
const EtchComponent = require('../etch-component')
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'})
)
)
)
)
}
}

View File

@@ -0,0 +1,121 @@
const etch = require('etch')
const EtchComponent = require('../etch-component')
const UpdateManager = require('../update-manager')
const $ = etch.dom
module.exports =
class UpdateView extends EtchComponent {
constructor (props) {
super(props)
if (this.props.updateManager.getAutoUpdatesEnabled() && this.props.updateManager.getState() === UpdateManager.State.Idle) {
this.props.updateManager.checkForUpdate()
}
}
handleAutoUpdateCheckbox (e) {
atom.config.set('core.automaticallyUpdate', e.target.checked)
}
shouldUpdateActionButtonBeDisabled () {
let {state} = this.props.updateManager
return state === UpdateManager.State.CheckingForUpdate || state === UpdateManager.State.DownloadingUpdate
}
executeUpdateAction () {
if (this.props.updateManager.state === UpdateManager.State.UpdateAvailableToInstall) {
this.props.updateManager.restartAndInstallUpdate()
} else {
this.props.updateManager.checkForUpdate()
}
}
renderUpdateStatus () {
let updateStatus = ''
switch (this.props.updateManager.state) {
case UpdateManager.State.Idle:
updateStatus = $.div({className: 'about-updates-item is-shown about-default-update-message'},
this.props.updateManager.getAutoUpdatesEnabled() ? 'Atom will check for updates automatically' : 'Automatic updates are disabled please check manually'
)
break
case UpdateManager.State.CheckingForUpdate:
updateStatus = $.div({className: 'about-updates-item app-checking-for-updates'},
$.span({className: 'about-updates-label icon icon-search'}, 'Checking for updates...')
)
break
case UpdateManager.State.DownloadingUpdate:
updateStatus = $.div({className: 'about-updates-item app-downloading-update'},
$.span({className: 'loading loading-spinner-tiny inline-block'}),
$.span({className: 'about-updates-label'}, 'Downloading update')
)
break
case UpdateManager.State.UpdateAvailableToInstall:
updateStatus = $.div({className: 'about-updates-item app-update-available-to-install'},
$.span({className: 'about-updates-label icon icon-squirrel'}, 'New update'),
$.span({className: 'about-updates-version'}, this.props.availableVersion),
$.a({className: 'about-updates-release-notes', onclick: this.props.viewUpdateReleaseNotes}, 'Release Notes')
)
break
case UpdateManager.State.UpToDate:
updateStatus = $.div({className: 'about-updates-item app-up-to-date'},
$.span({className: 'icon icon-check'}),
$.span({className: 'about-updates-label is-strong'}, 'Atom is up to date!')
)
break
case UpdateManager.State.Unsupported:
updateStatus = $.div({className: 'about-updates-item app-unsupported'},
$.span({className: 'about-updates-label is-strong'}, 'Your system does not support automatic updates'),
$.a({className: 'about-updates-instructions', onclick: this.props.viewUpdateInstructions}, 'How to update')
)
break
case UpdateManager.State.Error:
updateStatus = $.div({className: 'about-updates-item app-update-error'},
$.span({className: 'icon icon-x'}),
$.span({className: 'about-updates-label app-error-message is-strong'}, this.props.updateManager.getErrorMessage())
)
break
}
return updateStatus
}
render () {
return $.div({className: 'about-updates group-start'},
$.div({className: 'about-updates-box'},
$.div({className: 'about-updates-status'}, this.renderUpdateStatus()),
$.button(
{
className: 'btn about-update-action-button',
disabled: this.shouldUpdateActionButtonBeDisabled(),
onclick: this.executeUpdateAction.bind(this),
style: {
display: this.props.updateManager.state === UpdateManager.State.Unsupported ? 'none' : 'block'
}
},
this.props.updateManager.state === 'update-available' ? 'Restart and install' : 'Check now'
)
),
$.div(
{
className: 'about-auto-updates',
style: {
display: this.props.updateManager.state === UpdateManager.State.Unsupported ? 'none' : 'block'
}
},
$.label({},
$.input(
{
className: 'input-checkbox',
type: 'checkbox',
checked: this.props.updateManager.getAutoUpdatesEnabled(),
onchange: this.handleAutoUpdateCheckbox.bind(this)
}
),
$.span({}, 'Automatically download updates')
)
)
)
}
}

View File

@@ -0,0 +1,57 @@
const etch = require('etch')
/*
Public: Abstract class for handling the initialization
boilerplate of an Etch component.
*/
module.exports =
class EtchComponent {
constructor (props) {
this.props = props
etch.initialize(this)
EtchComponent.setScheduler(atom.views)
}
/*
Public: Gets the scheduler Etch uses for coordinating DOM updates.
Returns a {Scheduler}
*/
static getScheduler () {
return etch.getScheduler()
}
/*
Public: Sets the scheduler Etch uses for coordinating DOM updates.
* `scheduler` {Scheduler}
*/
static setScheduler (scheduler) {
etch.setScheduler(scheduler)
}
/*
Public: Updates the component's properties and re-renders it. Only the
properties you specify in this object will update any other properties
the component stores will be unaffected.
* `props` an {Object} representing the properties you want to update
*/
update (props) {
let oldProps = this.props
this.props = Object.assign({}, oldProps, props)
return etch.update(this)
}
/*
Public: Destroys the component, removing it from the DOM.
*/
destroy () {
etch.destroy(this)
}
render () {
throw new Error('Etch components must implement a `render` method')
}
}

View File

@@ -0,0 +1,96 @@
const {CompositeDisposable} = require('atom')
const semver = require('semver')
const UpdateManager = require('./update-manager')
const About = require('./about')
const StatusBarView = require('./components/about-status-bar')
let updateManager
// The local storage key for the available update version.
const AvailableUpdateVersion = 'about:version-available'
const AboutURI = 'atom://about'
module.exports = {
activate () {
this.subscriptions = new CompositeDisposable()
this.createModel()
let availableVersion = window.localStorage.getItem(AvailableUpdateVersion)
if (atom.getReleaseChannel() === 'dev' || (availableVersion && semver.lte(availableVersion, atom.getVersion()))) {
this.clearUpdateState()
}
this.subscriptions.add(updateManager.onDidChange(() => {
if (updateManager.getState() === UpdateManager.State.UpdateAvailableToInstall) {
window.localStorage.setItem(AvailableUpdateVersion, updateManager.getAvailableVersion())
this.showStatusBarIfNeeded()
}
}))
this.subscriptions.add(atom.commands.add('atom-workspace', 'about:clear-update-state', () => {
this.clearUpdateState()
}))
},
deactivate () {
this.model.destroy()
if (this.statusBarTile) this.statusBarTile.destroy()
if (updateManager) {
updateManager.dispose()
updateManager = undefined
}
},
clearUpdateState () {
window.localStorage.removeItem(AvailableUpdateVersion)
},
consumeStatusBar (statusBar) {
this.statusBar = statusBar
this.showStatusBarIfNeeded()
},
deserializeAboutView (state) {
if (!this.model) {
this.createModel()
}
return this.model.deserialize(state)
},
createModel () {
updateManager = updateManager || new UpdateManager()
this.model = new About({
uri: AboutURI,
currentAtomVersion: atom.getVersion(),
currentElectronVersion: process.versions.electron,
currentChromeVersion: process.versions.chrome,
currentNodeVersion: process.version,
updateManager: updateManager
})
},
isUpdateAvailable () {
let availableVersion = window.localStorage.getItem(AvailableUpdateVersion)
return availableVersion && semver.gt(availableVersion, atom.getVersion())
},
showStatusBarIfNeeded () {
if (this.isUpdateAvailable() && this.statusBar) {
let statusBarView = new StatusBarView()
if (this.statusBarTile) {
this.statusBarTile.destroy()
}
this.statusBarTile = this.statusBar.addRightTile({
item: statusBarView,
priority: -100
})
return this.statusBarTile
}
}
}

View File

@@ -0,0 +1,146 @@
const {Emitter, CompositeDisposable} = require('atom')
const Unsupported = 'unsupported'
const Idle = 'idle'
const CheckingForUpdate = 'checking'
const DownloadingUpdate = 'downloading'
const UpdateAvailableToInstall = 'update-available'
const UpToDate = 'no-update-available'
const ErrorState = 'error'
let UpdateManager = class UpdateManager {
constructor () {
this.emitter = new Emitter()
this.currentVersion = atom.getVersion()
this.availableVersion = atom.getVersion()
this.resetState()
this.listenForAtomEvents()
}
listenForAtomEvents () {
this.subscriptions = new CompositeDisposable()
this.subscriptions.add(
atom.autoUpdater.onDidBeginCheckingForUpdate(() => {
this.setState(CheckingForUpdate)
}),
atom.autoUpdater.onDidBeginDownloadingUpdate(() => {
this.setState(DownloadingUpdate)
}),
atom.autoUpdater.onDidCompleteDownloadingUpdate(({releaseVersion}) => {
this.setAvailableVersion(releaseVersion)
}),
atom.autoUpdater.onUpdateNotAvailable(() => {
this.setState(UpToDate)
}),
atom.autoUpdater.onUpdateError(() => {
this.setState(ErrorState)
}),
atom.config.observe('core.automaticallyUpdate', (value) => {
this.autoUpdatesEnabled = value
this.emitDidChange()
})
)
// TODO: When https://github.com/atom/electron/issues/4587 is closed we can add this support.
// atom.autoUpdater.onUpdateAvailable =>
// @find('.about-updates-item').removeClass('is-shown')
// @updateAvailable.addClass('is-shown')
}
dispose () {
this.subscriptions.dispose()
}
onDidChange (callback) {
return this.emitter.on('did-change', callback)
}
emitDidChange () {
this.emitter.emit('did-change')
}
getAutoUpdatesEnabled () {
return this.autoUpdatesEnabled && this.state !== UpdateManager.State.Unsupported
}
setAutoUpdatesEnabled (enabled) {
return atom.config.set('core.automaticallyUpdate', enabled)
}
getErrorMessage () {
return atom.autoUpdater.getErrorMessage()
}
getState () {
return this.state
}
setState (state) {
this.state = state
this.emitDidChange()
}
resetState () {
this.state = atom.autoUpdater.platformSupportsUpdates() ? atom.autoUpdater.getState() : Unsupported
this.emitDidChange()
}
getAvailableVersion () {
return this.availableVersion
}
setAvailableVersion (version) {
this.availableVersion = version
if (this.availableVersion !== this.currentVersion) {
this.state = UpdateAvailableToInstall
} else {
this.state = UpToDate
}
this.emitDidChange()
}
checkForUpdate () {
atom.autoUpdater.checkForUpdate()
}
restartAndInstallUpdate () {
atom.autoUpdater.restartAndInstallUpdate()
}
getReleaseNotesURLForCurrentVersion () {
return this.getReleaseNotesURLForVersion(this.currentVersion)
}
getReleaseNotesURLForAvailableVersion () {
return this.getReleaseNotesURLForVersion(this.availableVersion)
}
getReleaseNotesURLForVersion (appVersion) {
// Dev versions will not have a releases page
if (appVersion.indexOf('dev') > -1) {
return 'https://atom.io/releases'
}
if (!appVersion.startsWith('v')) {
appVersion = `v${appVersion}`
}
const releaseRepo = appVersion.indexOf('nightly') > -1 ? 'atom-nightly-releases' : 'atom'
return `https://github.com/atom/${releaseRepo}/releases/tag/${appVersion}`
}
}
UpdateManager.State = {
Unsupported: Unsupported,
Idle: Idle,
CheckingForUpdate: CheckingForUpdate,
DownloadingUpdate: DownloadingUpdate,
UpdateAvailableToInstall: UpdateAvailableToInstall,
UpToDate: UpToDate,
Error: ErrorState
}
module.exports = UpdateManager

1806
packages/about/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
{
"name": "about",
"author": "Machisté N. Quintana <mnquintana@users.noreply.github.com>",
"main": "./lib/main",
"version": "1.9.1",
"description": "View useful information about your Atom installation.",
"keywords": [],
"repository": "https://github.com/atom/about",
"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"
},
"consumedServices": {
"status-bar": {
"versions": {
"^1.0.0": "consumeStatusBar"
}
}
},
"deserializers": {
"AboutView": "deserializeAboutView"
},
"standard": {
"env": [
"browser",
"node",
"atomtest",
"jasmine"
],
"globals": [
"atom"
]
}
}

View File

@@ -0,0 +1,101 @@
const {it, fit, ffit, fffit, beforeEach, afterEach} = require('./helpers/async-spec-helpers') // eslint-disable-line no-unused-vars
describe('About', () => {
let workspaceElement
beforeEach(async () => {
let storage = {}
spyOn(window.localStorage, 'setItem').andCallFake((key, value) => {
storage[key] = value
})
spyOn(window.localStorage, 'getItem').andCallFake((key) => {
return storage[key]
})
workspaceElement = atom.views.getView(atom.workspace)
await atom.packages.activatePackage('about')
})
it('deserializes correctly', () => {
let deserializedAboutView = atom.deserializers.deserialize({
deserializer: 'AboutView',
uri: 'atom://about'
})
expect(deserializedAboutView).toBeTruthy()
})
describe('when the about:about-atom command is triggered', () => {
it('shows the About Atom 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
// workspaceElement to the DOM are generally slower than those off DOM.
jasmine.attachToDOM(workspaceElement)
expect(workspaceElement.querySelector('.about')).not.toExist()
await atom.workspace.open('atom://about')
let aboutElement = workspaceElement.querySelector('.about')
expect(aboutElement).toBeVisible()
})
})
describe('when the Atom version number is clicked', () => {
it('copies the version number to the clipboard', async () => {
await atom.workspace.open('atom://about')
let aboutElement = workspaceElement.querySelector('.about')
let versionContainer = aboutElement.querySelector('.atom')
versionContainer.click()
expect(atom.clipboard.read()).toBe(atom.getVersion())
})
})
describe('when the show more link is clicked', () => {
it('expands to show additional version numbers', async () => {
await atom.workspace.open('atom://about')
jasmine.attachToDOM(workspaceElement)
let aboutElement = workspaceElement.querySelector('.about')
let showMoreElement = aboutElement.querySelector('.show-more-expand')
let moreInfoElement = workspaceElement.querySelector('.show-more')
showMoreElement.click()
expect(moreInfoElement).toBeVisible()
})
})
describe('when the Electron version number is clicked', () => {
it('copies the version number to the clipboard', async () => {
await atom.workspace.open('atom://about')
let aboutElement = workspaceElement.querySelector('.about')
let versionContainer = aboutElement.querySelector('.electron')
versionContainer.click()
expect(atom.clipboard.read()).toBe(process.versions.electron)
})
})
describe('when the Chrome version number is clicked', () => {
it('copies the version number to the clipboard', async () => {
await atom.workspace.open('atom://about')
let aboutElement = workspaceElement.querySelector('.about')
let versionContainer = aboutElement.querySelector('.chrome')
versionContainer.click()
expect(atom.clipboard.read()).toBe(process.versions.chrome)
})
})
describe('when the Node version number is clicked', () => {
it('copies the version number to the clipboard', async () => {
await atom.workspace.open('atom://about')
let aboutElement = workspaceElement.querySelector('.about')
let versionContainer = aboutElement.querySelector('.node')
versionContainer.click()
expect(atom.clipboard.read()).toBe(process.version)
})
})
})

View File

@@ -0,0 +1,179 @@
const {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} = require('./helpers/async-spec-helpers') // eslint-disable-line no-unused-vars
const MockUpdater = require('./mocks/updater')
describe('the status bar', () => {
let atomVersion
let workspaceElement
beforeEach(async () => {
let storage = {}
spyOn(window.localStorage, 'setItem').andCallFake((key, value) => {
storage[key] = value
})
spyOn(window.localStorage, 'getItem').andCallFake((key) => {
return storage[key]
})
spyOn(atom, 'getVersion').andCallFake(() => {
return atomVersion
})
workspaceElement = atom.views.getView(atom.workspace)
await atom.packages.activatePackage('status-bar')
await atom.workspace.open('sample.js')
})
afterEach(async () => {
await atom.packages.deactivatePackage('about')
await atom.packages.deactivatePackage('status-bar')
})
describe('on a stable version', function () {
beforeEach(async () => {
atomVersion = '1.2.3'
await atom.packages.activatePackage('about')
})
describe('with no update', () => {
it('does not show the view', () => {
expect(workspaceElement).not.toContain('.about-release-notes')
})
})
describe('with an update', () => {
it('shows the view when the update finishes downloading', () => {
MockUpdater.finishDownloadingUpdate('42.0.0')
expect(workspaceElement).toContain('.about-release-notes')
})
describe('clicking on the status', () => {
it('opens the about page', async () => {
MockUpdater.finishDownloadingUpdate('42.0.0')
workspaceElement.querySelector('.about-release-notes').click()
await conditionPromise(() => workspaceElement.querySelector('.about'))
expect(workspaceElement.querySelector('.about')).toExist()
})
})
it('continues to show the squirrel until Atom is updated to the new version', async () => {
MockUpdater.finishDownloadingUpdate('42.0.0')
expect(workspaceElement).toContain('.about-release-notes')
await atom.packages.deactivatePackage('about')
expect(workspaceElement).not.toContain('.about-release-notes')
await atom.packages.activatePackage('about')
await Promise.resolve() // Service consumption hooks are deferred until the next tick
expect(workspaceElement).toContain('.about-release-notes')
await atom.packages.deactivatePackage('about')
expect(workspaceElement).not.toContain('.about-release-notes')
atomVersion = '42.0.0'
await atom.packages.activatePackage('about')
await Promise.resolve() // Service consumption hooks are deferred until the next tick
expect(workspaceElement).not.toContain('.about-release-notes')
})
it('does not show the view if Atom is updated to a newer version than notified', async () => {
MockUpdater.finishDownloadingUpdate('42.0.0')
await atom.packages.deactivatePackage('about')
atomVersion = '43.0.0'
await atom.packages.activatePackage('about')
await Promise.resolve() // Service consumption hooks are deferred until the next tick
expect(workspaceElement).not.toContain('.about-release-notes')
})
})
})
describe('on a beta version', function () {
beforeEach(async () => {
atomVersion = '1.2.3-beta4'
await atom.packages.activatePackage('about')
})
describe('with no update', () => {
it('does not show the view', () => {
expect(workspaceElement).not.toContain('.about-release-notes')
})
})
describe('with an update', () => {
it('shows the view when the update finishes downloading', () => {
MockUpdater.finishDownloadingUpdate('42.0.0')
expect(workspaceElement).toContain('.about-release-notes')
})
describe('clicking on the status', () => {
it('opens the about page', async () => {
MockUpdater.finishDownloadingUpdate('42.0.0')
workspaceElement.querySelector('.about-release-notes').click()
await conditionPromise(() => workspaceElement.querySelector('.about'))
expect(workspaceElement.querySelector('.about')).toExist()
})
})
it('continues to show the squirrel until Atom is updated to the new version', async () => {
MockUpdater.finishDownloadingUpdate('42.0.0')
expect(workspaceElement).toContain('.about-release-notes')
await atom.packages.deactivatePackage('about')
expect(workspaceElement).not.toContain('.about-release-notes')
await atom.packages.activatePackage('about')
await Promise.resolve() // Service consumption hooks are deferred until the next tick
expect(workspaceElement).toContain('.about-release-notes')
await atom.packages.deactivatePackage('about')
expect(workspaceElement).not.toContain('.about-release-notes')
atomVersion = '42.0.0'
await atom.packages.activatePackage('about')
await Promise.resolve() // Service consumption hooks are deferred until the next tick
expect(workspaceElement).not.toContain('.about-release-notes')
})
it('does not show the view if Atom is updated to a newer version than notified', async () => {
MockUpdater.finishDownloadingUpdate('42.0.0')
await atom.packages.deactivatePackage('about')
atomVersion = '43.0.0'
await atom.packages.activatePackage('about')
await Promise.resolve() // Service consumption hooks are deferred until the next tick
expect(workspaceElement).not.toContain('.about-release-notes')
})
})
})
describe('on a development version', function () {
beforeEach(async () => {
atomVersion = '1.2.3-dev-0123abcd'
await atom.packages.activatePackage('about')
})
describe('with no update', () => {
it('does not show the view', () => {
expect(workspaceElement).not.toContain('.about-release-notes')
})
})
describe('with a previously downloaded update', () => {
it('does not show the view', () => {
window.localStorage.setItem('about:version-available', '42.0.0')
expect(workspaceElement).not.toContain('.about-release-notes')
})
})
})
})

View File

@@ -0,0 +1,65 @@
/** @babel */
const {now} = Date
const {setTimeout} = global
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) {
global[name](description, function () {
const result = fn()
if (result instanceof Promise) {
waitsForPromise(() => result)
}
})
}
})
export async function conditionPromise (condition) {
const startTime = now()
while (true) {
await timeoutPromise(100)
if (await condition()) {
return
}
if (now() - startTime > 5000) {
throw new Error('Timed out waiting on condition')
}
}
}
export function timeoutPromise (timeout) {
return new Promise(function (resolve) {
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()
})
})
}

View File

@@ -0,0 +1,21 @@
module.exports = {
updateError () {
atom.autoUpdater.emitter.emit('update-error')
},
checkForUpdate () {
atom.autoUpdater.emitter.emit('did-begin-checking-for-update')
},
updateNotAvailable () {
atom.autoUpdater.emitter.emit('update-not-available')
},
downloadUpdate () {
atom.autoUpdater.emitter.emit('did-begin-downloading-update')
},
finishDownloadingUpdate (releaseVersion) {
atom.autoUpdater.emitter.emit('did-complete-downloading-update', {releaseVersion})
}
}

View File

@@ -0,0 +1,22 @@
const UpdateManager = require('../lib/update-manager')
describe('UpdateManager', () => {
let updateManager
beforeEach(() => {
updateManager = new UpdateManager()
})
describe('::getReleaseNotesURLForVersion', () => {
it('returns atom.io releases when dev version', () => {
expect(updateManager.getReleaseNotesURLForVersion('1.7.0-dev-e44b57d')).toContain('atom.io/releases')
})
it('returns the page for the release when not a dev version', () => {
expect(updateManager.getReleaseNotesURLForVersion('1.7.0')).toContain('atom/atom/releases/tag/v1.7.0')
expect(updateManager.getReleaseNotesURLForVersion('v1.7.0')).toContain('atom/atom/releases/tag/v1.7.0')
expect(updateManager.getReleaseNotesURLForVersion('1.7.0-beta10')).toContain('atom/atom/releases/tag/v1.7.0-beta10')
expect(updateManager.getReleaseNotesURLForVersion('1.7.0-nightly10')).toContain('atom/atom-nightly-releases/releases/tag/v1.7.0-nightly10')
})
})
})

View File

@@ -0,0 +1,280 @@
const {shell} = require('electron')
const {it, fit, ffit, fffit, beforeEach, afterEach} = require('./helpers/async-spec-helpers') // eslint-disable-line no-unused-vars
const main = require('../lib/main')
const AboutView = require('../lib/components/about-view')
const UpdateView = require('../lib/components/update-view')
const MockUpdater = require('./mocks/updater')
describe('UpdateView', () => {
let aboutElement
let updateManager
let workspaceElement
let scheduler
beforeEach(async () => {
let storage = {}
spyOn(window.localStorage, 'setItem').andCallFake((key, value) => {
storage[key] = value
})
spyOn(window.localStorage, 'getItem').andCallFake((key) => {
return storage[key]
})
workspaceElement = atom.views.getView(atom.workspace)
await atom.packages.activatePackage('about')
spyOn(atom.autoUpdater, 'getState').andReturn('idle')
spyOn(atom.autoUpdater, 'checkForUpdate')
spyOn(atom.autoUpdater, 'platformSupportsUpdates').andReturn(true)
})
describe('when the About page is open', () => {
beforeEach(async () => {
jasmine.attachToDOM(workspaceElement)
await atom.workspace.open('atom://about')
aboutElement = workspaceElement.querySelector('.about')
updateManager = main.model.state.updateManager
scheduler = AboutView.getScheduler()
})
describe('when the updates are not supported by the platform', () => {
beforeEach(async () => {
atom.autoUpdater.platformSupportsUpdates.andReturn(false)
updateManager.resetState()
await scheduler.getNextUpdatePromise()
})
it('hides the auto update UI and shows the update instructions link', async () => {
expect(aboutElement.querySelector('.about-update-action-button')).not.toBeVisible()
expect(aboutElement.querySelector('.about-auto-updates')).not.toBeVisible()
})
it('opens the update instructions page when the instructions link is clicked', async () => {
spyOn(shell, 'openExternal')
let link = aboutElement.querySelector('.app-unsupported .about-updates-instructions')
link.click()
let args = shell.openExternal.mostRecentCall.args
expect(shell.openExternal).toHaveBeenCalled()
expect(args[0]).toContain('installing-atom')
})
})
describe('when updates are supported by the platform', () => {
beforeEach(async () => {
atom.autoUpdater.platformSupportsUpdates.andReturn(true)
updateManager.resetState()
await scheduler.getNextUpdatePromise()
})
it('shows the auto update UI', () => {
expect(aboutElement.querySelector('.about-updates')).toBeVisible()
})
it('shows the correct panels when the app checks for updates and there is no update available', async () => {
expect(aboutElement.querySelector('.about-default-update-message')).toBeVisible()
MockUpdater.checkForUpdate()
await scheduler.getNextUpdatePromise()
expect(aboutElement.querySelector('.app-up-to-date')).not.toBeVisible()
expect(aboutElement.querySelector('.app-checking-for-updates')).toBeVisible()
MockUpdater.updateNotAvailable()
await scheduler.getNextUpdatePromise()
expect(aboutElement.querySelector('.app-up-to-date')).toBeVisible()
expect(aboutElement.querySelector('.app-checking-for-updates')).not.toBeVisible()
})
it('shows the correct panels when the app checks for updates and encounters an error', async () => {
expect(aboutElement.querySelector('.about-default-update-message')).toBeVisible()
MockUpdater.checkForUpdate()
await scheduler.getNextUpdatePromise()
expect(aboutElement.querySelector('.app-up-to-date')).not.toBeVisible()
expect(aboutElement.querySelector('.app-checking-for-updates')).toBeVisible()
spyOn(atom.autoUpdater, 'getErrorMessage').andReturn('an error message')
MockUpdater.updateError()
await scheduler.getNextUpdatePromise()
expect(aboutElement.querySelector('.app-update-error')).toBeVisible()
expect(aboutElement.querySelector('.app-error-message').textContent).toBe('an error message')
expect(aboutElement.querySelector('.app-checking-for-updates')).not.toBeVisible()
expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(false)
expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Check now')
})
it('shows the correct panels and button states when the app checks for updates and an update is downloaded', async () => {
expect(aboutElement.querySelector('.about-default-update-message')).toBeVisible()
expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(false)
expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Check now')
MockUpdater.checkForUpdate()
await scheduler.getNextUpdatePromise()
expect(aboutElement.querySelector('.app-up-to-date')).not.toBeVisible()
expect(aboutElement.querySelector('.app-checking-for-updates')).toBeVisible()
expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(true)
expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Check now')
MockUpdater.downloadUpdate()
await scheduler.getNextUpdatePromise()
expect(aboutElement.querySelector('.app-checking-for-updates')).not.toBeVisible()
expect(aboutElement.querySelector('.app-downloading-update')).toBeVisible()
// TODO: at some point it would be nice to be able to cancel an update download, and then this would be a cancel button
expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(true)
expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Check now')
MockUpdater.finishDownloadingUpdate('42.0.0')
await scheduler.getNextUpdatePromise()
expect(aboutElement.querySelector('.app-downloading-update')).not.toBeVisible()
expect(aboutElement.querySelector('.app-update-available-to-install')).toBeVisible()
expect(aboutElement.querySelector('.app-update-available-to-install .about-updates-version').textContent).toBe('42.0.0')
expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(false)
expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Restart and install')
})
it('opens the release notes for the downloaded release when the release notes link are clicked', async () => {
MockUpdater.finishDownloadingUpdate('1.2.3')
await scheduler.getNextUpdatePromise()
spyOn(shell, 'openExternal')
let link = aboutElement.querySelector('.app-update-available-to-install .about-updates-release-notes')
link.click()
let args = shell.openExternal.mostRecentCall.args
expect(shell.openExternal).toHaveBeenCalled()
expect(args[0]).toContain('/v1.2.3')
})
it('executes checkForUpdate() when the check for update button is clicked', () => {
let button = aboutElement.querySelector('.about-update-action-button')
button.click()
expect(atom.autoUpdater.checkForUpdate).toHaveBeenCalled()
})
it('executes restartAndInstallUpdate() when the restart and install button is clicked', async () => {
spyOn(atom.autoUpdater, 'restartAndInstallUpdate')
MockUpdater.finishDownloadingUpdate('42.0.0')
await scheduler.getNextUpdatePromise()
let button = aboutElement.querySelector('.about-update-action-button')
button.click()
expect(atom.autoUpdater.restartAndInstallUpdate).toHaveBeenCalled()
})
it("starts in the same state as atom's AutoUpdateManager", async () => {
atom.autoUpdater.getState.andReturn('downloading')
updateManager.resetState()
await scheduler.getNextUpdatePromise()
expect(aboutElement.querySelector('.app-checking-for-updates')).not.toBeVisible()
expect(aboutElement.querySelector('.app-downloading-update')).toBeVisible()
expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(true)
expect(aboutElement.querySelector('.about-update-action-button').textContent).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 the About page is not open and an update is downloaded', () => {
it('should display the new version when it is opened', async () => {
MockUpdater.finishDownloadingUpdate('42.0.0')
jasmine.attachToDOM(workspaceElement)
await atom.workspace.open('atom://about')
aboutElement = workspaceElement.querySelector('.about')
updateManager = main.model.state.updateManager
scheduler = AboutView.getScheduler()
expect(aboutElement.querySelector('.app-update-available-to-install')).toBeVisible()
expect(aboutElement.querySelector('.app-update-available-to-install .about-updates-version').textContent).toBe('42.0.0')
expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(false)
expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Restart and install')
})
})
})

View File

@@ -0,0 +1,175 @@
@import "ui-variables";
@import "variables";
.about {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
-webkit-user-select: none;
cursor: default;
overflow: auto;
text-align: center;
font-size: 1.25em;
line-height: 1.4;
padding: 4em;
color: @text-color;
background-color: @base-background-color;
button {
cursor: default;
}
a:focus {
// Don't use Bootstrap default here
color: inherit;
}
img, a {
-webkit-user-drag: none;
}
.input-checkbox {
margin-top: -.2em;
}
// used to group different elements
.group-start {
margin-top: 4em;
}
.group-item {
margin-top: 1.5em;
}
}
.about-container {
width: 100%;
max-width: 500px;
}
// Header --------------------------------
.about-atom-io:hover {
.about-logo {
color: @atom-green;
}
}
.about-logo {
display: block;
width: 100%;
max-width: 280px;
margin: 0 auto 1em auto;
color: @text-color-highlight;
transition: color 0.2s;
}
.about-version-container {
&:hover {
color: lighten(@text-color, 15%);
}
&:active {
color: lighten(@text-color, 30%);
}
}
.about-version {
margin-right: .5em;
font-size: 1.25em;
vertical-align: middle;
}
.about-more-version {
color: @text-color-subtle;
font-size: .9em;
}
.about-header-release-notes {
vertical-align: middle;
margin-left: 1em;
}
// Updates --------------------------------
.about-updates {
width: 100%;
max-width: 500px;
}
.about-updates-box {
display: flex;
align-items: center;
padding: @component-padding;
border: 1px solid @base-border-color;
border-radius: @component-border-radius * 2;
background-color: @background-color-highlight;
}
.about-updates-status {
flex: 1;
margin-left: .5em;
text-align: left;
}
.about-updates-item,
.about-default-update-message .about-updates-label {
display: block;
}
.about-updates-label {
color: @text-color-subtle;
&.is-strong {
color: @text-color;
}
}
.about-updates-version {
margin: 0 .4em;
}
.about-updates-release-notes,
.about-updates-instructions {
margin: 0 1em 0 1.5em;
}
.about-auto-updates {
margin-top: 1em;
input {
margin-right: .5em;
}
}
// Love --------------------------------
.about-love {
.icon::before {
// Make these octicons look good inlined with text
position: relative;
width: auto;
height: auto;
margin-right: 0;
font-size: 1.5em;
vertical-align: text-top;
}
.icon-logo-github::before {
font-size: 3.6em;
height: .36em;
}
}
.about-credits {
color: @text-color-subtle;
}
// the blue squirrel --------------------------------
.about-release-notes {
color: @background-color-info;
&:hover {
color: lighten(@background-color-info, 15%);
}
}

View File

@@ -0,0 +1 @@
@atom-green: #40a977;

View File

@@ -0,0 +1,20 @@
Copyright (c) 2016 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.

View File

@@ -0,0 +1,11 @@
## One Dark Syntax theme
![one-dark-syntax](https://user-images.githubusercontent.com/238929/40553597-5f741518-6000-11e8-9068-70dfc5008b54.png)
> The font used in the screenshot is [Fira Mono](https://github.com/mozilla/Fira).
There is also a matching [UI theme](https://atom.io/themes/one-dark-ui).
### Install
This theme is installed by default with Atom and can be activated by going to the __Settings > Themes__ section and selecting it from the __Syntax Themes__ drop-down menu.

View File

@@ -0,0 +1,23 @@
// Atom Syntax Theme: One
@import "styles/syntax-variables.less";
@import "styles/editor.less";
@import "styles/syntax/_base.less";
@import "styles/syntax/c.less";
@import "styles/syntax/cpp.less";
@import "styles/syntax/cs.less";
@import "styles/syntax/css.less";
@import "styles/syntax/elixir.less";
@import "styles/syntax/gfm.less";
@import "styles/syntax/go.less";
@import "styles/syntax/ini.less";
@import "styles/syntax/java.less";
@import "styles/syntax/javascript.less";
@import "styles/syntax/json.less";
@import "styles/syntax/ng.less";
@import "styles/syntax/ruby.less";
@import "styles/syntax/php.less";
@import "styles/syntax/python.less";

View File

@@ -0,0 +1,16 @@
{
"name": "one-dark-syntax",
"theme": "syntax",
"version": "1.8.4",
"description": "A dark syntax theme",
"keywords": [
"dark",
"blue",
"syntax"
],
"repository": "https://github.com/atom/one-dark-syntax",
"license": "MIT",
"engines": {
"atom": ">0.50.0"
}
}

View File

@@ -0,0 +1,31 @@
// Config -----------------------------------
@syntax-hue: 220;
@syntax-saturation: 13%;
@syntax-brightness: 18%;
// Monochrome -----------------------------------
@mono-1: hsl(@syntax-hue, 14%, 71%); // default text
@mono-2: hsl(@syntax-hue, 9%, 55%);
@mono-3: hsl(@syntax-hue, 10%, 40%);
// Colors -----------------------------------
@hue-1: hsl(187, 47%, 55%); // <-cyan
@hue-2: hsl(207, 82%, 66%); // <-blue
@hue-3: hsl(286, 60%, 67%); // <-purple
@hue-4: hsl( 95, 38%, 62%); // <-green
@hue-5: hsl(355, 65%, 65%); // <-red 1
@hue-5-2: hsl( 5, 48%, 51%); // <-red 2
@hue-6: hsl( 29, 54%, 61%); // <-orange 1
@hue-6-2: hsl( 39, 67%, 69%); // <-orange 2
// Base colors -----------------------------------
@syntax-fg: @mono-1;
@syntax-bg: hsl(@syntax-hue, @syntax-saturation, @syntax-brightness);
@syntax-gutter: darken(@syntax-fg, 26%);
@syntax-guide: fade(@syntax-fg, 15%);
@syntax-accent: hsl(@syntax-hue, 100%, 66% );

View File

@@ -0,0 +1,96 @@
// Editor styles (background, gutter, guides)
atom-text-editor {
background-color: @syntax-background-color;
color: @syntax-text-color;
.line.cursor-line {
background-color: @syntax-cursor-line;
}
.invisible {
color: @syntax-text-color;
}
.cursor {
border-left: 2px solid @syntax-cursor-color;
}
.selection .region {
background-color: @syntax-selection-color;
}
.bracket-matcher .region {
border-bottom: 1px solid @syntax-cursor-color;
box-sizing: border-box;
}
.invisible-character {
color: @syntax-invisible-character-color;
}
.indent-guide {
color: @syntax-indent-guide-color;
}
.wrap-guide {
background-color: @syntax-wrap-guide-color;
}
// find + replace
.find-result .region.region.region,
.current-result .region.region.region {
border-radius: 2px;
background-color: @syntax-result-marker-color;
transition: border-color .4s;
}
.find-result .region.region.region {
border: 2px solid transparent;
}
.current-result .region.region.region {
border: 2px solid @syntax-result-marker-color-selected;
transition-duration: .1s;
}
.gutter {
.line-number {
color: @syntax-gutter-text-color;
-webkit-font-smoothing: antialiased;
&.cursor-line {
color: @syntax-gutter-text-color-selected;
background-color: @syntax-gutter-background-color-selected;
}
&.cursor-line-no-selection {
background-color: transparent;
}
.icon-right {
color: @syntax-text-color;
}
}
&:not(.git-diff-icon) .line-number.git-line-removed {
&.git-line-removed::before {
bottom: -3px;
}
&::after {
content: "";
position: absolute;
left: 0px;
bottom: 0px;
width: 25px;
border-bottom: 1px dotted fade(@syntax-color-removed, 50%);
pointer-events: none;
}
}
}
.gutter .line-number.folded,
.gutter .line-number:after,
.fold-marker:after {
color: @syntax-gutter-text-color-selected;
}
}

View File

@@ -0,0 +1,56 @@
@import "colors.less";
// Official Syntax Variables -----------------------------------
// General colors
@syntax-text-color: @syntax-fg;
@syntax-cursor-color: @syntax-accent;
@syntax-selection-color: lighten(@syntax-background-color, 10%);
@syntax-selection-flash-color: @syntax-accent;
@syntax-background-color: @syntax-bg;
// Guide colors
@syntax-wrap-guide-color: @syntax-guide;
@syntax-indent-guide-color: @syntax-guide;
@syntax-invisible-character-color: @syntax-guide;
// For find and replace markers
@syntax-result-marker-color: fade(@syntax-accent, 24%);
@syntax-result-marker-color-selected: @syntax-accent;
// Gutter colors
@syntax-gutter-text-color: @syntax-gutter;
@syntax-gutter-text-color-selected: @syntax-fg;
@syntax-gutter-background-color: @syntax-bg; // unused
@syntax-gutter-background-color-selected: lighten(@syntax-bg, 8%);
// Git colors - For git diff info. i.e. in the gutter
@syntax-color-renamed: hsl(208, 100%, 60%);
@syntax-color-added: hsl(150, 60%, 54%);
@syntax-color-modified: hsl(40, 60%, 70%);
@syntax-color-removed: hsl(0, 70%, 60%);
// For language entity colors
@syntax-color-variable: @hue-5;
@syntax-color-constant: @hue-6;
@syntax-color-property: @syntax-fg;
@syntax-color-value: @syntax-fg;
@syntax-color-function: @hue-2;
@syntax-color-method: @hue-2;
@syntax-color-class: @hue-6-2;
@syntax-color-keyword: @hue-3;
@syntax-color-tag: @hue-5;
@syntax-color-attribute: @hue-6;
@syntax-color-import: @hue-3;
@syntax-color-snippet: @hue-4;
// Custom Syntax Variables -----------------------------------
// Don't use in packages
@syntax-cursor-line: hsla(@syntax-hue, 100%, 80%, .04); // needs to be semi-transparent to show search results
@syntax-deprecated-fg: darken(@syntax-color-modified, 50%);
@syntax-deprecated-bg: @syntax-color-modified;
@syntax-illegal-fg: white;
@syntax-illegal-bg: @syntax-color-removed;

View File

@@ -0,0 +1,310 @@
// Language syntax highlighting
.syntax--comment {
color: @mono-3;
font-style: italic;
.syntax--markup.syntax--link {
color: @mono-3;
}
}
.syntax--entity {
&.syntax--name.syntax--type {
color: @hue-6-2;
}
&.syntax--other.syntax--inherited-class {
color: @hue-4;
}
}
.syntax--keyword {
color: @hue-3;
&.syntax--control {
color: @hue-3;
}
&.syntax--operator {
color: @mono-1;
}
&.syntax--other.syntax--special-method {
color: @hue-2;
}
&.syntax--other.syntax--unit {
color: @hue-6;
}
}
.syntax--storage {
color: @hue-3;
&.syntax--type {
&.syntax--annotation,
&.syntax--primitive {
color: @hue-3;
}
}
&.syntax--modifier {
&.syntax--package,
&.syntax--import {
color: @mono-1;
}
}
}
.syntax--constant {
color: @hue-6;
&.syntax--variable {
color: @hue-6;
}
&.syntax--character.syntax--escape {
color: @hue-1;
}
&.syntax--numeric {
color: @hue-6;
}
&.syntax--other.syntax--color {
color: @hue-1;
}
&.syntax--other.syntax--symbol {
color: @hue-1;
}
}
.syntax--variable {
color: @hue-5;
&.syntax--interpolation {
color: @hue-5-2;
}
&.syntax--parameter {
color: @mono-1;
}
}
.syntax--string {
color: @hue-4;
> .syntax--source, .syntax--embedded {
color: @mono-1;
}
&.syntax--regexp {
color: @hue-1;
.syntax--source.syntax--ruby.syntax--embedded {
color: @hue-6-2;
}
}
&.syntax--other.syntax--link {
color: @hue-5;
}
}
.syntax--punctuation {
&.syntax--definition {
&.syntax--comment {
color: @mono-3;
}
&.syntax--method-parameters,
&.syntax--function-parameters,
&.syntax--parameters,
&.syntax--separator,
&.syntax--seperator,
&.syntax--array {
color: @mono-1;
}
&.syntax--heading,
&.syntax--identity {
color: @hue-2;
}
&.syntax--bold {
color: @hue-6-2;
font-weight: bold;
}
&.syntax--italic {
color: @hue-3;
font-style: italic;
}
}
&.syntax--section {
&.syntax--embedded {
color: @hue-5-2;
}
&.syntax--method,
&.syntax--class,
&.syntax--inner-class {
color: @mono-1;
}
}
}
.syntax--support {
&.syntax--class {
color: @hue-6-2;
}
&.syntax--type {
color: @hue-1;
}
&.syntax--function {
color: @hue-1;
&.syntax--any-method {
color: @hue-2;
}
}
}
.syntax--entity {
&.syntax--name.syntax--function {
color: @hue-2;
}
&.syntax--name.syntax--class,
&.syntax--name.syntax--type.syntax--class {
color: @hue-6-2;
}
&.syntax--name.syntax--section {
color: @hue-2;
}
&.syntax--name.syntax--tag {
color: @hue-5;
}
&.syntax--other.syntax--attribute-name {
color: @hue-6;
&.syntax--id {
color: @hue-2;
}
}
}
.syntax--meta {
&.syntax--class {
color: @hue-6-2;
&.syntax--body {
color: @mono-1;
}
}
&.syntax--method-call,
&.syntax--method {
color: @mono-1;
}
&.syntax--definition {
&.syntax--variable {
color: @hue-5;
}
}
&.syntax--link {
color: @hue-6;
}
&.syntax--require {
color: @hue-2;
}
&.syntax--selector {
color: @hue-3;
}
&.syntax--separator {
color: @mono-1;
}
&.syntax--tag {
color: @mono-1;
}
}
.syntax--underline {
text-decoration: underline;
}
.syntax--none {
color: @mono-1;
}
.syntax--invalid {
&.syntax--deprecated {
color: @syntax-deprecated-fg !important;
background-color: @syntax-deprecated-bg !important;
}
&.syntax--illegal {
color: @syntax-illegal-fg !important;
background-color: @syntax-illegal-bg !important;
}
}
// Languages -------------------------------------------------
.syntax--markup {
&.syntax--bold {
color: @hue-6;
font-weight: bold;
}
&.syntax--changed {
color: @hue-3;
}
&.syntax--deleted {
color: @hue-5;
}
&.syntax--italic {
color: @hue-3;
font-style: italic;
}
&.syntax--heading {
color: @hue-5;
.syntax--punctuation.syntax--definition.syntax--heading {
color: @hue-2;
}
}
&.syntax--link {
color: @hue-1;
}
&.syntax--inserted {
color: @hue-4;
}
&.syntax--quote {
color: @hue-6;
}
&.syntax--raw {
color: @hue-4;
}
}

View File

@@ -0,0 +1,5 @@
.syntax--source.syntax--c {
.syntax--keyword.syntax--operator {
color: @hue-3;
}
}

View File

@@ -0,0 +1,5 @@
.syntax--source.syntax--cpp {
.syntax--keyword.syntax--operator {
color: @hue-3;
}
}

View File

@@ -0,0 +1,5 @@
.syntax--source.syntax--cs {
.syntax--keyword.syntax--operator {
color: @hue-3;
}
}

View File

@@ -0,0 +1,10 @@
.syntax--source.syntax--css {
// highlight properties/values if they are supported
.syntax--property-name,
.syntax--property-value {
color: @mono-2;
&.syntax--support {
color: @mono-1;
}
}
}

View File

@@ -0,0 +1,47 @@
.syntax--source.syntax--elixir {
.syntax--source.syntax--embedded.syntax--source {
color: @mono-1;
}
.syntax--constant.syntax--language,
.syntax--constant.syntax--numeric,
.syntax--constant.syntax--definition {
color: @hue-2;
}
.syntax--variable.syntax--definition,
.syntax--variable.syntax--anonymous{
color: @hue-3;
}
.syntax--parameter.syntax--variable.syntax--function {
color: @hue-6;
font-style: italic;
}
.syntax--quoted{
color: @hue-4;
}
.syntax--keyword.syntax--special-method,
.syntax--embedded.syntax--section,
.syntax--embedded.syntax--source.syntax--empty, {
color: @hue-5;
}
.syntax--readwrite.syntax--module {
.syntax--punctuation {
color: @hue-5;
}
}
.syntax--regexp.syntax--section,
.syntax--regexp.syntax--string {
color: @hue-5-2;
}
.syntax--separator,
.syntax--keyword.syntax--operator {
color: @hue-6;
}
.syntax--variable.syntax--constant {
color: @hue-6-2;
}
.syntax--array,
.syntax--scope,
.syntax--section {
color: @mono-2;
}
}

View File

@@ -0,0 +1,9 @@
.syntax--source.syntax--gfm {
.syntax--markup {
-webkit-font-smoothing: auto;
}
.syntax--link .syntax--entity {
color: @hue-2;
}
}

View File

@@ -0,0 +1,5 @@
.syntax--source.syntax--go {
.syntax--storage.syntax--type.syntax--string {
color: @hue-3;
}
}

View File

@@ -0,0 +1,5 @@
.syntax--source.syntax--ini {
.syntax--keyword.syntax--other.syntax--definition.syntax--ini {
color: @hue-5;
}
}

View File

@@ -0,0 +1,24 @@
.syntax--source.syntax--java {
.syntax--storage {
&.syntax--modifier.syntax--import {
color: @hue-6-2;
}
&.syntax--type {
color: @hue-6-2;
}
}
.syntax--keyword.syntax--operator.syntax--instanceof {
color: @hue-3;
}
}
.syntax--source.syntax--java-properties {
.syntax--meta.syntax--key-pair {
color: @hue-5;
& > .syntax--punctuation {
color: @mono-1;
}
}
}

View File

@@ -0,0 +1,17 @@
.syntax--source.syntax--js {
.syntax--keyword.syntax--operator {
color: @hue-1;
// keywords are definded in https://github.com/atom/language-javascript/blob/master/grammars/javascript.cson
// search "instanceof" for location
&.syntax--delete,
&.syntax--in,
&.syntax--of,
&.syntax--instanceof,
&.syntax--new,
&.syntax--typeof,
&.syntax--void {
color: @hue-3;
}
}
}

View File

@@ -0,0 +1,21 @@
.syntax--source.syntax--json {
.syntax--meta.syntax--structure.syntax--dictionary.syntax--json {
& > .syntax--string.syntax--quoted.syntax--json {
& > .syntax--punctuation.syntax--string {
color: @hue-5;
}
color: @hue-5;
}
}
.syntax--meta.syntax--structure.syntax--dictionary.syntax--json, .syntax--meta.syntax--structure.syntax--array.syntax--json {
& > .syntax--value.syntax--json > .syntax--string.syntax--quoted.syntax--json,
& > .syntax--value.syntax--json > .syntax--string.syntax--quoted.syntax--json > .syntax--punctuation {
color: @hue-4;
}
& > .syntax--constant.syntax--language.syntax--json {
color: @hue-1;
}
}
}

View File

@@ -0,0 +1,47 @@
.syntax--ng {
&.syntax--interpolation {
color: @hue-5;
&.syntax--begin, &.syntax--end {
color: @hue-2;
}
.syntax--function {
color: @hue-5;
&.syntax--begin, &.syntax--end {
color: @hue-2;
}
}
.syntax--bool {
color: @hue-6;
}
.syntax--bracket {
color: @mono-1;
}
}
&.syntax--pipe, &.syntax--operator {
color: @mono-1;
}
&.syntax--tag {
color: @hue-1;
}
&.syntax--attribute-with-value {
.syntax--attribute-name {
color: @hue-6-2;
}
.syntax--string {
color: @hue-3;
&.syntax--begin, &.syntax--end {
color: @mono-1;
}
}
}
}

View File

@@ -0,0 +1,5 @@
.syntax--source.syntax--php {
.syntax--class.syntax--bracket {
color: @mono-1;
}
}

View File

@@ -0,0 +1,9 @@
.syntax--source.syntax--python {
.syntax--keyword.syntax--operator.syntax--logical.syntax--python {
color: @hue-3;
}
.syntax--variable.syntax--parameter {
color: @hue-6;
}
}

View File

@@ -0,0 +1,5 @@
.syntax--source.syntax--ruby {
.syntax--constant.syntax--other.syntax--symbol > .syntax--punctuation {
color: inherit;
}
}

View File

@@ -0,0 +1 @@
spec/fixtures

1
packages/one-light-ui/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
node_modules

View File

@@ -0,0 +1,20 @@
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.

View File

@@ -0,0 +1,42 @@
## One Light UI theme
A light UI theme that adapts to most syntax themes.
![One light UI](https://cloud.githubusercontent.com/assets/378023/26246819/0826f04e-3cd6-11e7-98eb-cd94bc48b090.png)
> The font used in the screenshot is [Fira Mono](https://github.com/mozilla/Fira).
### Install
This theme comes bundled with Atom and can be activated by going to the __Settings > Themes__ section and selecting "One Light" from the __UI Themes__ drop-down menu.
### Settings
In the theme settings you can:
- Change the __Font Size__ to scale the whole UI up or down.
- Choose between 3 __Tab Sizing__ modes.
- Hide the __dock buttons__.
To make changes, go to `Settings > Themes > One Light UI > Settings` or the cog icon next to the theme picker.
### Customize
It's also possible to resize only certain areas by adding the following to your `styles.less` (Use DevTools to find the right selectors):
```css
.theme-one-light-ui {
.tab-bar { font-size: 18px; }
.tree-view { font-size: 14px; }
.status-bar { font-size: 12px; }
}
```
### FAQ
__Why do the colors change when I switch Syntax themes.__
This UI theme uses the same background color as the chosen syntax theme. If that syntax theme has a dark background color, it only uses its hue, but otherwise stays light. This lets you use light-dark combos.

View File

@@ -0,0 +1,37 @@
{
"max_line_length": {
"level": "ignore"
},
"no_empty_param_list": {
"level": "error"
},
"arrow_spacing": {
"level": "error"
},
"no_interpolation_in_single_quotes": {
"level": "error"
},
"no_debugger": {
"level": "error"
},
"prefer_english_operator": {
"level": "error"
},
"colon_assignment_spacing": {
"spacing": {
"left": 0,
"right": 1
},
"level": "error"
},
"braces_spacing": {
"spaces": 0,
"level": "error"
},
"spacing_after_comma": {
"level": "error"
},
"no_stand_alone_at": {
"level": "error"
}
}

View File

@@ -0,0 +1,35 @@
// Atom UI Theme: One
@import "styles/ui-variables.less";
@import "styles/ui-mixins.less";
@import "octicon-mixins.less"; // https://github.com/atom/atom/blob/master/static/variables/octicon-mixins.less
@import "styles/atom.less";
@import "styles/badges.less";
@import "styles/buttons.less";
@import "styles/docks.less";
@import "styles/editor.less";
@import "styles/git.less";
@import "styles/inputs.less";
@import "styles/lists.less";
@import "styles/messages.less";
@import "styles/nav.less";
@import "styles/notifications.less";
@import "styles/modal.less";
@import "styles/panels.less";
@import "styles/panes.less";
@import "styles/progress.less";
@import "styles/tabs.less";
@import "styles/text.less";
@import "styles/title-bar.less";
@import "styles/tooltips.less";
@import "styles/tree-view.less";
@import "styles/status-bar.less";
@import "styles/key-binding.less";
@import "styles/sites.less";
@import "styles/settings.less";
@import "styles/packages.less";
@import "styles/core.less";
@import "styles/config.less";

View File

@@ -0,0 +1,86 @@
root = document.documentElement
themeName = 'one-light-ui'
module.exports =
activate: (state) ->
atom.config.observe "#{themeName}.fontSize", (value) ->
setFontSize(value)
atom.config.observe "#{themeName}.tabSizing", (value) ->
setTabSizing(value)
atom.config.observe "#{themeName}.tabCloseButton", (value) ->
setTabCloseButton(value)
atom.config.observe "#{themeName}.hideDockButtons", (value) ->
setHideDockButtons(value)
atom.config.observe "#{themeName}.stickyHeaders", (value) ->
setStickyHeaders(value)
# DEPRECATED: This can be removed at some point (added in Atom 1.17/1.18ish)
# It removes `layoutMode`
if atom.config.get("#{themeName}.layoutMode")
atom.config.unset("#{themeName}.layoutMode")
deactivate: ->
unsetFontSize()
unsetTabSizing()
unsetTabCloseButton()
unsetHideDockButtons()
unsetStickyHeaders()
# Font Size -----------------------
setFontSize = (currentFontSize) ->
root.style.fontSize = "#{currentFontSize}px"
unsetFontSize = ->
root.style.fontSize = ''
# Tab Sizing -----------------------
setTabSizing = (tabSizing) ->
root.setAttribute("theme-#{themeName}-tabsizing", tabSizing.toLowerCase())
unsetTabSizing = ->
root.removeAttribute("theme-#{themeName}-tabsizing")
# Tab Close Button -----------------------
setTabCloseButton = (tabCloseButton) ->
if tabCloseButton is 'Left'
root.setAttribute("theme-#{themeName}-tab-close-button", 'left')
else
unsetTabCloseButton()
unsetTabCloseButton = ->
root.removeAttribute("theme-#{themeName}-tab-close-button")
# Dock Buttons -----------------------
setHideDockButtons = (hideDockButtons) ->
if hideDockButtons
root.setAttribute("theme-#{themeName}-dock-buttons", 'hidden')
else
unsetHideDockButtons()
unsetHideDockButtons = ->
root.removeAttribute("theme-#{themeName}-dock-buttons")
# Sticky Headers -----------------------
setStickyHeaders = (stickyHeaders) ->
if stickyHeaders
root.setAttribute("theme-#{themeName}-sticky-headers", 'sticky')
else
unsetStickyHeaders()
unsetStickyHeaders = ->
root.removeAttribute("theme-#{themeName}-sticky-headers")

View File

@@ -0,0 +1,78 @@
{
"name": "one-light-ui",
"theme": "ui",
"version": "1.12.5",
"description": "Atom One light UI theme",
"keywords": [
"light",
"adaptive",
"ui"
],
"license": "MIT",
"repository": "https://github.com/atom/one-light-ui",
"main": "lib/main",
"engines": {
"atom": ">0.40.0"
},
"devDependencies": {
"coffeelint": "^1.9.7"
},
"configSchema": {
"fontSize": {
"title": "Font Size",
"description": "Change the font size for the UI.",
"type": "integer",
"default": 12,
"enum": [
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20
],
"order": 1
},
"tabSizing": {
"title": "Tab Sizing",
"description": "In Even mode all tabs will be the same size. Great for quickly closing many tabs. In Maximum mode the tabs will expand to take up the full width. In Minimum mode the tabs will only take as little space as needed and also show longer file names.",
"type": "string",
"default": "Even",
"enum": [
"Even",
"Maximum",
"Minimum"
],
"order": 2
},
"tabCloseButton": {
"title": "Tab Close Button",
"description": "Choose the position of the close button shown in tabs.",
"type": "string",
"default": "Right",
"enum": [
"Left",
"Right"
],
"order": 3
},
"hideDockButtons": {
"title": "Hide dock toggle buttons",
"description": "Note: When hiding the toggle buttons, opening a dock needs to be done by using the keyboard or other alternatives.",
"type": "boolean",
"default": "false",
"order": 4
},
"stickyHeaders": {
"title": "Make tree-view project headers sticky",
"type": "boolean",
"default": "false",
"order": 5
}
}
}

View File

@@ -0,0 +1,36 @@
themeName = 'one-light-ui'
describe "#{themeName} theme", ->
beforeEach ->
waitsForPromise ->
atom.packages.activatePackage(themeName)
it "allows the font size to be set via config", ->
expect(document.documentElement.style.fontSize).toBe '12px'
atom.config.set("#{themeName}.fontSize", '10')
expect(document.documentElement.style.fontSize).toBe '10px'
it "allows the tab sizing to be set via config", ->
atom.config.set("#{themeName}.tabSizing", 'Maximum')
expect(document.documentElement.getAttribute("theme-#{themeName}-tabsizing")).toBe 'maximum'
it "allows the tab sizing to be set via config", ->
atom.config.set("#{themeName}.tabSizing", 'Minimum')
expect(document.documentElement.getAttribute("theme-#{themeName}-tabsizing")).toBe 'minimum'
it "allows the tab close button to be shown on the left via config", ->
atom.config.set("#{themeName}.tabCloseButton", 'Left')
expect(document.documentElement.getAttribute("theme-#{themeName}-tab-close-button")).toBe 'left'
it "allows the dock toggle buttons to be hidden via config", ->
atom.config.set("#{themeName}.hideDockButtons", true)
expect(document.documentElement.getAttribute("theme-#{themeName}-dock-buttons")).toBe 'hidden'
it "allows the tree-view headers to be sticky via config", ->
atom.config.set("#{themeName}.stickyHeaders", true)
expect(document.documentElement.getAttribute("theme-#{themeName}-sticky-headers")).toBe 'sticky'
it "allows the tree-view headers to not be sticky via config", ->
atom.config.set("#{themeName}.stickyHeaders", false)
expect(document.documentElement.getAttribute("theme-#{themeName}-sticky-headers")).toBe null

View File

@@ -0,0 +1,67 @@
* {
box-sizing: border-box;
}
html {
font-size: @font-size;
}
atom-workspace {
background-color: @app-background-color;
}
// Scrollbars ------------------------------------
.scrollbars-visible-always {
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
background: @scrollbar-background-color;
}
::-webkit-scrollbar-thumb {
border-radius: 5px;
border: 3px solid @scrollbar-background-color;
background: @scrollbar-color;
background-clip: content-box;
}
::-webkit-scrollbar-corner {
background: @scrollbar-background-color;
}
::-webkit-scrollbar-thumb:vertical:active {
border-radius: 0;
border-left-width: 0;
border-right-width: 0;
}
::-webkit-scrollbar-thumb:horizontal:active {
border-radius: 0;
border-top-width: 0;
border-bottom-width: 0;
}
atom-text-editor {
::-webkit-scrollbar-track {
background: @scrollbar-background-color-editor;
}
::-webkit-scrollbar-corner {
background: @scrollbar-background-color-editor;
}
::-webkit-scrollbar-thumb {
border-color: @scrollbar-background-color-editor;
background: @scrollbar-color-editor;
}
}
}
// TODO: Move to a better place, not sure where it gets used
.caret {
border-top: 5px solid #fff;
margin-top: -1px;
}

View File

@@ -0,0 +1,14 @@
.badge {
padding: @ui-padding/4 @ui-padding/2.5;
min-width: @ui-padding*1.25;
.text(highlight);
border-radius: @ui-size*2;
background-color: @badge-background-color;
// Icon ----------------------
&.icon {
font-size: @ui-size;
padding: @ui-padding-icon @ui-padding-icon*1.5;
}
}

View File

@@ -0,0 +1,186 @@
@btn-border: 1px solid @button-border-color;
@btn-padding: 0 @ui-size/1.25;
// Mixins -----------------------
.btn-default (@color, @hover-color, @selected-color, @text-color) {
color: @text-color;
text-shadow: none;
border: @btn-border;
background-color: @color;
background-image: linear-gradient(lighten(@color, 2%), @color);
&:hover {
color: @text-color-highlight;
background-image: linear-gradient(lighten(@hover-color, 2%), @hover-color);
}
&:active {
background: darken(@color, 4%);
box-shadow: none;
}
&.selected {
background: @selected-color;
}
&.selected:focus,
&.selected:hover {
background: lighten(@selected-color, 2%);
}
&:focus {
.focus(); // unfortunately :focus styles stay even after releasing mouse.
}
}
.btn-variant (@color) {
@_text-color: contrast(@color, white, hsl(0,0%,20%), 33% );
.btn-default(
@color,
lighten(@color, 3%),
saturate(darken(@color, 12%), 20%),
@text-color-highlight
);
color: @_text-color;
& when (@ui-lightness > 50%) {
border-color: transparent; // hide border on light backgrounds
}
&:hover,
&:focus {
color: @_text-color;
}
&:focus {
border-color: transparent;
background-clip: padding-box;
box-shadow: inset 0 0 0 1px fade(@base-border-color, 50%), 0 0 0 1px @color;
}
&.icon:before {
color: @_text-color;
}
}
// Buttons -----------------------
.btn {
height: initial;
padding: @btn-padding;
font-size: @ui-size;
line-height: @ui-line-height;
}
.btn,
.btn.btn-default {
.btn-default(@button-background-color, @button-background-color-hover, @button-background-color-selected, @text-color);
}
.btn.btn-primary {
.btn-variant(@accent-bg-color);
}
.btn.btn-info {
.btn-variant(@background-color-info);
}
.btn.btn-success {
.btn-variant(@background-color-success);
}
.btn.btn-warning {
.btn-variant(@background-color-warning);
}
.btn.btn-error {
.btn-variant(@background-color-error);
}
// Button Sizes -----------------------
.btn.btn-xs,
.btn-group-xs > .btn {
font-size: @ui-size*.8;
line-height: @ui-line-height;
padding: @btn-padding;
}
.btn.btn-sm,
.btn-group-sm > .btn {
font-size: @ui-size*.9;
line-height: @ui-line-height;
padding: @btn-padding;
}
.btn.btn-lg,
.btn-group-lg > .btn {
font-size: @ui-size * 1.5;
line-height: @ui-line-height;
padding: @btn-padding;
}
// Button Group -----------------------
.btn-group > .btn {
z-index: 0;
&:hover {
z-index: 0;
}
&.btn:focus {
z-index: 1;
.focus();
}
&:first-child {
border-left: @btn-border;
}
&:last-child,
&.selected:last-child {
border-right: @btn-border;
}
// hide border on light backgrounds
& when (@ui-lightness > 50%) {
&.btn-primary:first-child,
&.btn-info:first-child,
&.btn-success:first-child,
&.btn-warning:first-child,
&.btn-error:first-child {
border-left-color: transparent;
}
&.btn-primary:last-child,
&.btn-info:last-child,
&.btn-success:last-child,
&.btn-warning:last-child,
&.btn-error:last-child {
border-right-color: transparent;
}
}
&.selected,
&.selected:first-child,
&.selected:last-child {
color: @button-text-color-selected;
border-color: @button-border-color-selected;
}
& when (@ui-lightness > 50%) {
&.selected + .btn {
border-left-color: @button-border-color-selected;
}
&.selected + .selected {
border-left-color: mix(@button-border-color, @button-border-color-selected);
}
}
&.selected:focus {
border-color: @button-background-color-selected;
box-shadow: inset 0 0 0 1px fade(@base-border-color, 50%), 0 0 0 1px @button-background-color-selected;
}
}
// Button Icons -----------------------
.btn.icon:before {
width: auto;
height: auto;
font-size: 1.333333em;
vertical-align: -.1em;
}

View File

@@ -0,0 +1,156 @@
// Theme config
// This gets changed from the theme settings
@theme-tabsizing: ~'theme-@{ui-theme-name}-tabsizing';
@theme-dockButtons: ~'theme-@{ui-theme-name}-dock-buttons';
@theme-stickyHeaders: ~'theme-@{ui-theme-name}-sticky-headers';
@theme-closeButton: ~'theme-@{ui-theme-name}-tab-close-button';
// Tabs ----------------------------------------------
@tab-min-width: 7em; // ~ icon + 6 characters
// Even (default)
.tab-bar {
.tab,
.tab.active {
flex: 1 1 0;
max-width: 22em;
min-width: @tab-min-width;
}
atom-dock & {
.tab,
.tab.active {
max-width: none;
}
}
// TODO: Turn this into a config
// Truncates the beginning instead
// .title.title.title {
// direction: rtl; // change direction
// }
}
// Maximum (full width)
[@{theme-tabsizing}="maximum"] .tab-bar {
.tab,
.tab.active {
max-width: none;
}
}
// Minimum (show long paths)
[@{theme-tabsizing}="minimum"] .tab-bar {
.tab,
.tab.active {
flex: 0 0 auto;
min-width: 2.75em;
max-width: @tab-min-width * 3.3;
}
atom-dock {
.tab,
.tab.active {
max-width: @tab-min-width * 2;
}
}
}
// Tabs: close button position ------------------------------
[@{theme-closeButton}="left"] {
.tab-bar .tab {
.close-icon {
right: auto;
left: @icon-padding-right;
}
}
}
// Hide docks toggle buttons ------------------------------
[@{theme-dockButtons}="hidden"] {
// Hide docks when not open
.atom-dock-inner:not(.atom-dock-open) {
display: none;
}
// Hide toggle buttons
.atom-dock-toggle-button {
display: none;
}
}
// Sticky Projects ------------------------------
[@{theme-stickyHeaders}="sticky"] {
.tree-view {
.project-root-header {
position: sticky;
top: 0;
z-index: 3;
padding-left: 5px;
padding-right: 10px;
border-bottom: 1px solid @base-border-color;
background-color: @tree-view-background-color;
}
.project-root.project-root {
margin-left: -5px;
margin-right: -10px;
// Disable selection
&::before {
display: none;
}
// Add selection back
&.selected .project-root-header {
background-color: @background-color-selected;
}
}
&:focus .selected .project-root-header.project-root-header {
background: @button-background-color-selected;
}
// Fix sticky header from covering auto-revealed files
.entry.file.selected {
padding-top: @ui-tab-height;
margin-top: -@ui-tab-height;
}
// Fix sticky header from covering auto-revealed directories when using up/down keys
// for directories, scroll test moves to .header, see https://github.com/atom/tree-view/blob/d2857ad4d7eeb7dad5cf94b33257a8740211480e/lib/tree-view.coffee#L839
.entry.directory.selected:not(.project-root) {
& > .header {
padding-top: @ui-tab-height;
margin-top: -@ui-tab-height;
}
&::before {
margin-top: @ui-tab-height;
}
}
// Fix above directory is not being clickable
.entry.directory:not(.project-root) > .header {
z-index: 2;
}
.entry.directory.selected:not(.project-root) > .header {
z-index: 1;
}
}
}

View File

@@ -0,0 +1,25 @@
// Misc
.preview-pane .results-view .path-match-number {
// show number also on selected item
color: inherit;
opacity: .6;
}
.tool-panel.incompatible-packages {
// incompatible-packages isn't really a tool-panel and more a whole pane
.text(normal);
background-color: @level-2-color;
}
// Styleguide ----------------------------------------------
.styleguide {
// Modal
atom-panel.modal:after {
position: absolute; // prevent overlay backdrop from leaking outside
left: -@ui-padding;
right: -@ui-padding;
bottom: -@ui-padding;
}
}

View File

@@ -0,0 +1,43 @@
// Docks ------------------------------
// Make handles not take up any space when dock is open
.atom-dock-resize-handle {
position: absolute;
z-index: 11; // same as toggle buttons
&.left {
top: 0;
right: 0;
bottom: 0;
}
&.right {
top: 0;
left: 0;
bottom: 0;
}
&.bottom {
top: 0;
left: 0;
right: 0;
}
}
// Add borders
.atom-dock-inner.atom-dock-open.left {
border-right: 1px solid @base-border-color;
}
.atom-dock-inner.atom-dock-open.right {
border-left: 1px solid @base-border-color;
}
// Make toggle buttons cover ^ border
.atom-dock-toggle-button.left {
margin-left: -2px;
}
.atom-dock-toggle-button.right {
margin-right: -2px;
}
.atom-dock-inner:not(.atom-dock-open) .atom-dock-toggle-button.bottom {
margin-bottom: -1px;
}

View File

@@ -0,0 +1,15 @@
.dropdown-menu {
background-color: @overlay-background-color;
border-radius: @component-border-radius;
border: 1px solid @base-border-color;
padding: 0;
> li > a {
.text(normal);
}
> li > a:hover {
.text(highlight);
background-color: @background-color-highlight;
}
}

View File

@@ -0,0 +1,44 @@
// Editor in a panel
// TODO: Find a better selector, maybe a new class like atom-text-editor[medium]
atom-panel-container atom-text-editor.is-focused {
.focus();
}
// Mini
// Usually just single line inputs
atom-text-editor[mini] {
overflow: auto;
font-size: @ui-input-size;
line-height: @ui-line-height;
max-height: @ui-line-height * 5; // rows
padding-left: @ui-padding/3;
border-radius: @component-border-radius;
color: @text-color-highlight;
border: 1px solid @input-border-color;
background-color: @input-background-color;
.placeholder-text {
color: @text-color-subtle;
}
.selection .region {
background-color: @input-selection-color;
}
.cursor {
border-color: @accent-color;
border-width: 2px;
}
&.is-focused {
.focus();
background-color: @input-background-color-focus;
.selection .region {
background-color: @input-selection-color-focus;
}
}
}

View File

@@ -0,0 +1,6 @@
.status { .text(normal); }
.status-added { .text(success); } // green
.status-ignored { .text(subtle); } // faded
.status-modified { .text(warning); } // orange
.status-removed { .text(error); } // red
.status-renamed { .text(info); } // blue

View File

@@ -0,0 +1,87 @@
//
// Checkbox
// -------------------------
.input-checkbox {
&:active {
background-color: @accent-color;
}
&:before,
&:after {
background-color: @accent-text-color;
}
&:checked {
background-color: @accent-color;
}
&:indeterminate {
background-color: @accent-color;
}
}
//
// Radio
// -------------------------
.input-radio {
&:before {
background-color: @accent-text-color;
}
&:active {
background-color: @accent-color;
}
&:checked {
background-color: @accent-color;
}
}
//
// Range (Slider)
// -------------------------
.input-range {
&::-webkit-slider-thumb {
background-color: @accent-color;
}
}
//
// Toggle
// -------------------------
.input-toggle {
&:checked {
background-color: @accent-color;
}
&:before {
background-color: @accent-text-color;
}
}
// States -------------------------
.input-text,
.input-search,
.input-number,
.input-textarea,
.input-select,
.input-color {
&:focus {
.focus();
}
}
.input-text,
.input-search,
.input-number,
.input-textarea {
&:invalid {
.invalid();
}
}

View File

@@ -0,0 +1,12 @@
.key-binding {
display: inline-block;
margin-left: @ui-padding-icon;
padding: 0 @ui-padding/4;
line-height: 2;
font-family: inherit;
font-size: max(1em, @ui-size*.85);
letter-spacing: @ui-size/10;
border-radius: @component-border-radius;
color: @accent-bg-text-color;
background-color: @accent-bg-color;
}

View File

@@ -0,0 +1,150 @@
.list-group,
.list-tree {
li:not(.list-nested-item),
li.list-nested-item > .list-item {
.text(normal);
}
.generate-list-item-text-color(@class) {
li:not(.list-nested-item).text-@{class},
li.list-nested-item.text-@{class} > .list-item {
.text(@class);
}
}
.generate-list-item-text-color(subtle);
.generate-list-item-text-color(info);
.generate-list-item-text-color(success);
.generate-list-item-text-color(warning);
.generate-list-item-text-color(error);
.generate-list-item-text-color(selected);
.generate-list-item-status-color(@color, @status) {
li:not(.list-nested-item).status-@{status},
li.list-nested-item.status-@{status} > .list-item {
color: @color;
}
li:not(.list-nested-item).selected.status-@{status},
li.list-nested-item.selected.status-@{status} > .list-item {
color: @color;
}
}
.generate-list-item-status-color(@text-color-added, added);
.generate-list-item-status-color(@text-color-ignored, ignored);
.generate-list-item-status-color(@text-color-modified, modified);
.generate-list-item-status-color(@text-color-removed, removed);
.generate-list-item-status-color(@text-color-renamed, renamed);
li:not(.list-nested-item).selected,
li.list-nested-item.selected > .list-item {
.text(selected);
}
.no-icon {
padding-left: calc(@ui-padding-icon ~"+" @component-icon-size);
}
}
.list-tree.has-collapsable-children .list-nested-item > .list-item::before {
text-align: center;
}
.select-list ol.list-group,
&.select-list ol.list-group {
li.two-lines {
.secondary-line {
color: @text-color-subtle;
}
&.selected .secondary-line {
color: fade(@text-color-highlight, 50%);
text-shadow: none;
}
}
// Reset icon to allow nesting
.icon {
display: initial;
height: initial;
}
// We want to highlight the background of the list items because we dont
// know their size.
li.selected {
background-color: @background-color-selected;
&:before{ display: none; }
}
&.mark-active {
@active-icon-size: 14px;
// pad in front of the text where the icon would be We'll pad the non-
// active items with a 'fake' icon so other classes can pad the item
// without worrying about the icon padding.
li:before {
content: '';
background-color: transparent;
position: static;
display: inline-block;
left: auto; right: auto;
height: @active-icon-size;
width: @active-icon-size;
font-size: @active-icon-size;
}
> li:not(.active):before {
margin-right: @ui-padding-icon;
}
li.active {
.octicon(check, @active-icon-size);
&:before {
margin-right: @ui-padding-icon;
color: @text-color-success;
}
}
}
}
.select-list.popover-list {
@popover-list-padding: @ui-padding/4;
background-color: @overlay-background-color;
box-shadow: 0 2px 8px 1px rgba(0, 0, 0, 0.3);
padding: @popover-list-padding;
border-radius: @component-border-radius;
atom-text-editor[mini] {
margin-bottom: @popover-list-padding;
}
ol.list-group {
margin-top: @popover-list-padding;
}
.list-group li {
padding-left: @popover-list-padding;
}
}
.ui-sortable {
li {
line-height: 2.5;
}
// For sortable lists in the settings view
li.ui-sortable-placeholder {
visibility: visible !important;
background-color: darken(@pane-item-background-color, 10%);
}
}
li.ui-draggable-dragging,
li.ui-sortable-helper {
line-height: @ui-line-height;
height: @ui-line-height;
border: 0;
border-radius: 0;
list-style: none;
padding: 0 @ui-padding;
background: @background-color-highlight;
box-shadow: 0 0 1px @base-border-color;
}

View File

@@ -0,0 +1,16 @@
background-tips ul.background-message {
font-weight: 500;
font-size: 2em;
color: @text-color-faded;
.message {
padding: 0 @component-padding * 10;
.keystroke {
white-space: nowrap;
vertical-align: middle;
line-height: 1;
padding: .1em .4em;
}
}
}

View File

@@ -0,0 +1,125 @@
@modal-padding: @ui-padding/2 @ui-padding/1.5;
@modal-width: @ui-size * 50;
atom-panel-container.modal {
position: absolute;
top: 0; left: 0; right: 0;
}
atom-panel.modal {
position: relative;
width: 100%;
max-width: @modal-width;
margin: 0 auto;
left: initial;
color: @text-color;
background-color: transparent;
padding: @ui-padding/2;
&.from-top {
top: @component-padding * 5;
}
atom-text-editor[mini] {
margin-bottom: @ui-padding/2;
}
.select-list ol.list-group,
&.select-list ol.list-group {
border: 1px solid @overlay-border-color;
background-color: lighten(@overlay-background-color, 2%);
&:empty {
border: none;
margin-top: 0;
}
li {
padding: @modal-padding;
line-height: @ui-line-height;
border-bottom: 1px solid @overlay-border-color;
&:last-of-type {
border-bottom: none;
}
.icon::before {
margin-left: 1px;
}
.icon.status {
float: right;
margin-left: @ui-padding-icon;
&:before {
margin-left: 0;
margin-right: 0;
}
}
&.selected {
.status.icon {
color: @text-color-selected;
}
}
}
}
.select-list .key-binding {
margin-top: -1px;
margin-left: @ui-padding/2;
margin-right: calc( -@ui-padding/3 ~"+" 1px);
}
.select-list .primary-line {
display: block;
}
& > * {
position: relative; // fixes stacking order
}
.command-palette {
padding: 1px; // prevents the box-shadow of the input from being cut off
background-color: @overlay-background-color;
}
// Container
&:before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 0;
background-color: @overlay-background-color;
border-radius: @component-border-radius*2;
box-shadow: 0 6px 12px -2px hsla(0,0%,0%,.4);
}
// Backdrop
// TODO: Add extra wrapper to translate individually or easier positioning
&:after {
content: "";
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
background: @overlay-backdrop-color;
opacity: @overlay-backdrop-opacity;
backface-visibility: hidden; // fixes scrollbar on retina screens
-webkit-animation: overlay-fade .24s cubic-bezier(0.215, 0.61, 0.355, 1);
}
@-webkit-keyframes overlay-fade {
0% { opacity: 0; }
100% { opacity: @overlay-backdrop-opacity; }
}
}

View File

@@ -0,0 +1,25 @@
.nav-tabs {
border-bottom: 1px solid @base-border-color;
li {
a,
&.active a {
border: none;
margin-right: 0px;
margin-bottom: 1px;
}
a:hover,
&.active a,
&.active a:hover {
background-color: @background-color-highlight;
border: none;
color: @text-color-selected;
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
}
&.active a {
background-color: @tab-background-color-active;
}
}
}

View File

@@ -0,0 +1,45 @@
atom-notifications {
font-size: @ui-size * 1.2;
atom-notification {
width: 32em;
&.has-detail {
width: 32em;
}
&:first-child.has-close .message {
padding-right: 9em;
}
&:only-child.has-close .message,
&.has-close .message {
padding-right: 2.5em;
}
.item {
padding: @ui-padding/2;
}
.detail,
.description {
font-size: .85em;
}
&.icon:before {
padding-top: .85em;
}
.close {
width: 2.5em;
height: 3em;
line-height: 3em;
font-size: inherit;
}
.close-all.btn {
top: .5em;
right: 2.5em;
}
.btn-copy-report {
line-height: 2em;
margin-left: .5em;
}
}
}

View File

@@ -0,0 +1,231 @@
// Overrides packages
// find-and-replace + project-find ---------------------------
.find-and-replace,
.project-find {
padding: @ui-padding/4;
.input-block-item {
padding: @ui-padding/4;
}
}
// find-and-replace
.find-and-replace {
.header,
.input-block {
min-width: @ui-size*22;
}
.input-block-item {
flex: 1 1 @ui-size*22;
}
.input-block-item--flex {
flex: 100 1 @ui-size*22;
}
.btn,
.btn-group-options .btn {
font-size: @ui-size*1.1;
padding: 0;
}
.btn-group-options .btn,
.btn-group-options .btn.option-selection,
.btn-group-options .btn.option-whole-word {
padding: 0;
font-size: @ui-input-size; // keep same as text input
}
.find-container atom-text-editor {
padding-right: @ui-size*5; // leave some room for the results count
}
.find-meta-container {
top: 0;
font-size: @ui-size;
line-height: @ui-size*2.5;
}
}
// project-find
.project-find {
.header,
.input-block {
min-width: @ui-size*15;
}
.input-block-item {
flex: 1 1 @ui-size*14;
}
.input-block-item--flex {
flex: 100 1 @ui-size*20;
}
.btn {
font-size: @ui-size*1.1;
padding: 0;
}
.btn-group-options .btn {
padding: 0;
font-size: @ui-input-size; // keep same as text input
}
}
// Colorize find-and-replace based on results
& when (@ui-hue >= 190) and (@ui-hue <= 340) {
.find-and-replace {
&.has-no-results .find-container atom-text-editor[mini].is-focused {
.invalid();
.selection .region {
background-color: mix(@text-color-error, @input-background-color, 50%);
}
.cursor {
border-color: @text-color-error;
}
}
&.has-results .find-container atom-text-editor[mini].is-focused {
.valid();
.selection .region {
background-color: mix(@text-color-success, @input-background-color, 50%);
}
.cursor {
border-color: @text-color-success;
}
}
&.has-results .find-container .result-counter { color: @text-color-success; }
&.has-no-results .find-container .result-counter { color: @text-color-error; }
}
}
// Timecop ---------------------------
.timecop {
.timecop-panel {
padding: @component-padding/2;
background-color: @level-2-color;
}
.tool-panel {
padding: @component-padding/2;
background-color: @level-2-color;
}
.inset-panel {
border: 1px solid @base-border-color;
}
.panel-heading {
.text(highlight);
border-color: @base-border-color;
background-color: @level-1-color;
}
.list-item .inline-block {
line-height: 1.5;
}
}
// Command Palette + Fuzzy Finder ---------------------------
.command-palette .list-group .character-match,
.fuzzy-finder .list-group .character-match {
color: @accent-only-text-color;
}
// Deprecation Cop ---------------------------
.deprecation-cop {
.deprecation-overview {
background-color: @level-2-color;
border-bottom: 1px solid @base-border-color;
}
}
// Tool Bar ---------------------------
.tool-bar {
// Make it look the same as other panels
background-color: @level-3-color;
border: none;
// just a single border + more spacing
&.tool-bar-horizontal .tool-bar-spacer {
border-left: 0 none;
margin-left: .5em;
margin-right: .5em;
}
&.tool-bar-vertical .tool-bar-spacer {
border-bottom: 0 none;
margin-top: .5em;
margin-bottom: .5em;
}
// only show button styles on hover
button.tool-bar-btn {
background-color: @level-3-color;
background-image: none;
border-color: @level-3-color;
}
}
// GitHub package ---------------------------------------------------
.github {
// Fix focus styles
// Since it's not possible to add a padding to <atom-text-editor>
// a pseudo element is used to add the border when focused.
&-CommitView-editor atom-text-editor.is-focused {
box-shadow: none;
&:before {
content: "";
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
border: 2px solid;
border-color: inherit;
border-radius: @component-border-radius;
}
}
// Add focus styles since :focus doesn't work
&-CommitView-coAuthorEditor {
&.is-focused {
.focus();
}
&.is-open {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.Select-option {
&.is-focused {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
color: @accent-text-color;
background-color: @accent-color;
}
}
.Select-menu-outer {
left: -2px;
right: -2px;
bottom: 100%;
border: 2px solid @accent-color;
background-color: @overlay-background-color;
}
}
}

View File

@@ -0,0 +1,64 @@
// Panels
atom-panel {
.text(normal);
position: relative;
border-bottom: 1px solid @base-border-color;
&.top {
border-right: 1px solid @base-border-color;
}
&.left {
border-right: 1px solid @base-border-color;
}
&.right {
border-left: 1px solid @base-border-color;
}
&.bottom {
border-right: 1px solid @base-border-color;
}
&.footer:last-child {
border-bottom: none;
}
&.tool-panel:empty {
border: none;
}
}
.panel {
&.bordered {
border: 1px solid @base-border-color;
border-radius: @component-border-radius;
}
}
.inset-panel {
position: relative;
background-color: @inset-panel-background-color;
border-radius: @component-border-radius;
&.bordered {
border: 1px solid @base-border-color;
border-radius: @component-border-radius;
}
& .panel-heading {
border-color: @inset-panel-border-color;
}
}
.panel-heading {
.text(normal);
border-bottom: 1px solid @panel-heading-border-color;
background-color: @panel-heading-background-color;
.btn {
padding-left: 8px;
padding-right: 8px;
.btn-default(
lighten(@button-background-color, 10%),
lighten(@button-background-color-hover, 10%),
lighten(@button-background-color-selected, 10%),
lighten(@text-color, 10%)
);
}
}

View File

@@ -0,0 +1,22 @@
atom-pane-container {
atom-pane {
position: relative;
border-right: 1px solid @base-border-color;
border-bottom: 1px solid @base-border-color;
.item-views {
// prevent atom-text-editor from leaking ouside might improve performance
overflow: hidden;
}
}
}
// Hide right-most border
atom-pane:only-child,
atom-pane-axis.pane-row > atom-pane:last-child,
atom-pane-axis.pane-column:last-child > atom-pane {
border-right: none;
}

View File

@@ -0,0 +1,94 @@
// Spinner ----------------------
@spinner-duration: 1.2s;
.loading-spinner(@size) {
position: relative;
display: block;
width: 1em;
height: 1em;
font-size: @size;
background: radial-gradient(@accent-color .1em, transparent .11em);
&::before,
&::after {
content: "";
position: absolute;
z-index: 10; // prevent sibling elements from getting their own layers
top: 0;
left: 0;
border-radius: 1em;
width: inherit;
height: inherit;
border-radius: 1em;
border: 2px solid;
-webkit-animation: spinner-animation @spinner-duration infinite;
-webkit-animation-fill-mode: backwards;
}
&::before {
border-color: @accent-color transparent transparent transparent;
}
&::after {
border-color: transparent lighten(@accent-color, 15%) transparent transparent;
-webkit-animation-delay: @spinner-duration/2;
}
&.inline-block {
display: inline-block;
}
}
@-webkit-keyframes spinner-animation {
0% { transform: rotateZ( 0deg); -webkit-animation-timing-function: cubic-bezier(0, 0, .8, .2); }
50% { transform: rotateZ(180deg); -webkit-animation-timing-function: cubic-bezier(.2, .8, 1, 1); }
100% { transform: rotateZ(360deg); }
}
// Spinner sizes
.loading-spinner-tiny { .loading-spinner(16px); &::before, &::after { border-width: 1px; } }
.loading-spinner-small { .loading-spinner(32px); }
.loading-spinner-medium { .loading-spinner(48px); }
.loading-spinner-large { .loading-spinner(64px); }
// Progress Bar ----------------------
@progress-height: 8px;
@progress-buffer-color: fade(@progress-background-color, 20%);
progress {
-webkit-appearance: none;
height: @progress-height;
border-radius: @component-border-radius;
background-color: @input-background-color;
box-shadow: inset 0 0 0 1px @input-border-color;
&::-webkit-progress-bar {
background-color: transparent;
}
&::-webkit-progress-value {
border-radius: @component-border-radius;
background-color: @progress-background-color;
}
// Is buffering (when no value is set)
&:indeterminate {
background-image:
linear-gradient(-45deg, transparent 33%, @progress-buffer-color 33%,
@progress-buffer-color 66%, transparent 66%);
background-size: 25px @progress-height, 100% 100%, 100% 100%;
// Plays animation for 1min (12runs) at normal speed,
// then slows down frame-rate for 9mins (108runs) to limit CPU usage
-webkit-animation: progress-buffering 5s linear 12,
progress-buffering 5s 60s steps(10) 108;
}
}
@-webkit-keyframes progress-buffering {
100% { background-position: -100px 0px; }
}

View File

@@ -0,0 +1,140 @@
// Settings
// Modular Scale (1.125): http://www.modularscale.com/?1&em&1.125&web&table
@ms-6: @ui-size * 2.027;
@ms-5: @ui-size * 1.802;
@ms-4: @ui-size * 1.602;
@ms-3: @ui-size * 1.424;
@ms-2: @ui-size * 1.266;
@ms-1: @ui-size * 1.125;
@ms-0: @ui-size * 1;
@ms_1: @ui-size * 0.889;
@ms_2: @ui-size * 0.790;
.settings-view {
// Menu ------------------------------
.config-menu {
position: relative;
min-width: @ui-size * 15;
max-width: @ui-size * 20;
border-width: 0 1px 0 0;
border-image: linear-gradient(@level-2-color 10px, @base-border-color 200px) 0 1 0 0 stretch;
background: @level-2-color;
.btn {
white-space: initial;
font-size: @ms_1;
line-height: 1;
padding: @ui-padding/3 @ui-padding/2;
&::before {
vertical-align: middle;
}
}
}
.nav {
& > li > a {
padding: @ui-padding/2 @ui-padding;
line-height: @ui-line-height;
}
}
// Sections ------------------------------
& > .panels {
background-color: @level-2-color;
}
.section-container {
max-width: @ui-size*60;
}
.sub-section {
margin: @ui-padding*3 0;
}
.section,
.section:first-child,
.section:last-child {
padding: @ui-padding*3;
}
.themes-panel .control-group {
margin-top: @ui-padding*2;
}
// Titles ------------------------------
.section .section-heading {
margin-bottom: @ui-padding/1.5;
}
.sub-section-heading.icon:before,
.section-heading.icon:before {
margin-right: @ui-padding-icon;
}
// Cards ------------------------------
.package-card {
padding: @ui-padding;
.meta-controls .status-indicator {
width: @ui-padding/4;
&:before {
content: "\00a0"; // fixes 0 height
}
}
}
// Components ------------------------------
.icon::before {
color: @text-color-subtle;
}
.editor-container {
margin: @ui-padding 0;
}
.form-control {
font-size: @ui-size*1.25;
height: @ui-line-height;
padding-top: 0;
padding-bottom: 0;
}
.update-all-button {
font-size: .75em;
}
.install-button {
.btn-variant(@accent-bg-color);
}
input[type="checkbox"] {
background-color: @background-color-selected;
&:active,
&:checked {
background-color: @accent-color;
}
&:before,
&:after {
background-color: @accent-text-color;
}
}
.search-container .btn {
font-size: @ui-input-size;
}
}

View File

@@ -0,0 +1,13 @@
// Site Colors
.ui-site(@num, @color) {
.ui-site-@{num} {
background-color: @color;
}
}
.ui-site(1, @ui-site-color-1);
.ui-site(2, @ui-site-color-2);
.ui-site(3, @ui-site-color-3);
.ui-site(4, @ui-site-color-4);
.ui-site(5, @ui-site-color-5);

View File

@@ -0,0 +1,97 @@
@status-bar-height: @ui-tab-height; // same as tabs
@status-bar-padding: @ui-padding;
.status-bar {
font-size: @ui-size;
height: @status-bar-height;
line-height: @status-bar-height;
background-color: @level-3-color;
.flexbox-repaint-hack {
padding: 0; // override default
}
// underlines should only be used for external links
a:hover,
a:focus {
text-decoration: none;
cursor: default;
}
.inline-block {
margin: 0; // override default
padding: 0 @status-bar-padding/2;
vertical-align: top;
&:hover {
text-decoration: none;
background-color: @level-3-color-hover;
}
&:active {
background-color: @level-3-color-active;
}
// reset on child inline-block
.inline-block {
margin: 0;
padding: 0;
}
}
.status-bar-right {
.inline-block {
margin-left: 0; // override default
}
}
.icon {
vertical-align: middle;
}
.icon::before {
font-size: 1.33333em; // should be 16px with a default of 12px
width: auto; // use natural width
line-height: 1;
height: 1em; // same as line-height
margin-right: .25em;
top: auto;
}
}
// Package overrides -------------------------------
.status-bar.status-bar {
// Read-only -> Remove hover effect
.is-read-only, // <- use this class in packages
status-bar-launch-mode,
busy-signal {
&:hover,
&:active,
.inline-block:hover,
.inline-block:active {
background-color: transparent;
}
}
// Remove underline
.package-updates-status-view,
.github-ChangedFilesCount {
&:hover,
&:focus {
text-decoration: none;
cursor: default;
}
}
// Remove margin for icon without text
status-bar-launch-mode::before, // Launch mode
.about-release-notes::before, // New release squirrel
.PortalStatusBarIndicator .icon::before, // Teletype
.icon.is-icon-only::before {
margin-right: 0;
}
.github-PushPull-label.is-push:empty { // GitHub package when nothing to push
margin-right: -.25em;
}
}

View File

@@ -0,0 +1,250 @@
// Tabs
@tab-border: 1px solid @tab-border-color;
@title-padding: .66em;
@icon-padding-top: .5em; // 2.5 (total) - 1.5 (text) / 2
@icon-padding-right: .5em;
.tab-bar {
position: relative;
height: @ui-tab-height;
box-shadow: inset 0 -1px 0 @tab-border-color;
background: @tab-bar-background-color;
overflow-x: auto;
overflow-y: hidden;
border-radius: 0;
&::-webkit-scrollbar {
display: none;
}
&:empty {
display: none;
}
// Tab ----------------------
.tab {
position: relative;
top: 0;
padding: 0;
margin: 0;
height: inherit;
font-size: inherit;
line-height: @ui-tab-height;
color: @tab-text-color;
background-color: @tab-background-color;
box-shadow: inherit;
border-left: @tab-border;
&.active {
color: @tab-text-color-active;
background-color: @tab-background-color-active;
box-shadow: none;
}
&:first-of-type {
border-left-color: transparent;
}
&:last-of-type {
// use box-shadow to not take up any space
box-shadow: inset 0 -1px 0 @tab-border-color, 1px 0 0 @base-border-color;
}
&.active:last-of-type {
box-shadow: 1px 0 0 @base-border-color;
}
// Title ----------------------
.title {
text-align: center;
margin: 0 @title-padding;
}
// VCS coloring ----------------------
&:not(.active) .status-added { color: @tab-inactive-status-added; }
&:not(.active) .status-modified { color: @tab-inactive-status-modified; }
// Icons ----------------------
.title.title:before {
margin-right: .3em;
width: auto;
height: auto;
line-height: 1;
font-size: 1.125em;
vertical-align: -.0625em; // Adjust center for the 0.1em font-size increase
}
// Close icon ----------------------
.close-icon {
top: @icon-padding-top;
right: @icon-padding-right;
z-index: 2;
font-size: 1em;
width: 1.5em;
height: 1.5em;
line-height: 1.5;
text-align: center;
border-radius: @component-border-radius;
background-color: inherit;
overflow: hidden;
transform: scale(0);
transition: transform .08s;
&:hover {
color: @accent-text-color;
background-color: @accent-color;
}
&:active {
background-color: fade(@accent-color, 50%);
}
&::before {
z-index: 1;
font-size: 1.1em;
vertical-align: -.05em; // Adjust center for the 0.1em font-size increase
width: auto;
height: auto;
pointer-events: none;
}
}
&:hover .close-icon {
transform: scale(1);
transition-duration: .16s;
}
}
// Modified icon ----------------------
.tab.modified {
&:hover .close-icon {
color: @accent-color;
&:hover {
color: @accent-bg-text-color;
}
}
&:not(:hover) .close-icon {
top: @icon-padding-top;
right: @icon-padding-right;
width: 1.5em;
height: 1.5em;
line-height: 1.5;
color: @accent-color;
border-radius: @component-border-radius;
border: none;
transform: scale(1);
&::before {
content: "\f052";
display: inline-block;
}
}
}
// Tabs in the docks ----------------------
atom-dock & {
.tab.active {
background-color: @tool-panel-background-color;
}
}
// Dragging ----------------------
.tab.is-dragging {
opacity: .5;
.close-icon,
&:before {
visibility: hidden;
}
}
.placeholder {
position: relative;
pointer-events: none;
// bar
&:before {
z-index: 1;
margin: 0;
width: 2px;
height: @ui-tab-height;
background-color: @accent-color;
}
// arrow
&:after {
z-index: 0;
top: @ui-tab-height/2;
margin: -4px 0 0 -3px;
border-radius: 0;
border: 4px solid @accent-color;
transform: rotate(45deg);
background: transparent;
}
&:last-child {
&:before {
margin-left: -2px;
}
&:after {
transform: none;
margin-left: -10px;
border-color: transparent @accent-color transparent transparent;
}
}
}
// Overrides ----------------------
// keep tabs same size when active
.tab,
.tab.active {
padding-right: 0;
.title {
padding: 0;
}
}
}
// Active pane marker --------------
atom-pane-axis > atom-pane.active,
atom-pane-container > atom-pane.pane {
.tab.active:before {
content: "";
position: absolute;
pointer-events: none;
z-index: 2;
top: 0;
left: -1px; // cover left border
bottom: 0;
width: 2px;
background: @accent-color;
}
}
// hide marker in docks
atom-dock .tab-bar .tab::before {
display: none;
}
// Custom tabs --------------
.tab-bar .tab.active {
&[data-type$="Editor"],
&[data-type$="AboutView"],
&[data-type$="TimecopView"],
&[data-type$="StyleguideView"],
&[data-type="MarkdownPreviewView"] {
color: @tab-text-color-editor;
background-color: @tab-background-color-editor; // Match syntax background color
}
}

View File

@@ -0,0 +1,84 @@
h1,
h2,
h3 {
line-height: 1em;
margin-bottom: 15px
}
h1 { font-size: 2em; }
h2 { font-size: 1.5em; }
h3 { font-size: 1.2em; }
p {
line-height: 1.6;
margin-bottom: 15px;
}
label {
font-weight: normal;
}
pre {
box-shadow: none;
color: @text-color;
background: @inset-panel-background-color;
border-radius: @component-border-radius;
border: none;
margin: 0;
}
code {
.text(highlight);
background: @background-color-highlight;
border-radius: @component-border-radius;
}
.selected { .text(highlight); }
.text-smaller { font-size: 0.9em; }
.text-subtle { .text(subtle); }
.text-highlight { .text(highlight); }
.text-error { .text(error); }
.text-info {
.text(info);
&:hover { color: @text-color-info; }
}
.text-warning {
.text(warning);
&:hover { color: @text-color-warning; }
}
.text-success {
.text(success);
&:hover { color: @text-color-success; }
}
.highlight-mixin {
padding: 1px 4px;
border-radius: 2px;
}
.highlight {
.highlight-mixin();
font-weight: 700;
color: @text-color-highlight;
background-color: @background-color-highlight;
}
.highlight-color(@name, @background-color) {
.highlight-@{name} {
.highlight-mixin();
font-weight: 500;
color: white;
text-shadow: 0 1px 0px hsla(0,0%,0%,.2);
background-color: @background-color;
}
}
.highlight-color( info, @background-color-info);
.highlight-color(warning, @background-color-warning);
.highlight-color( error, @background-color-error);
.highlight-color(success, @background-color-success);
.results-view .path-details.list-item {
color: darken(@text-color-highlight, 18%);
}

View File

@@ -0,0 +1,4 @@
.title-bar {
height: 22px; // remove 1px since there is no border
border-bottom: none;
}

View File

@@ -0,0 +1,53 @@
.tooltip {
white-space: nowrap;
font-size: @ui-size*1.15;
&.in {
opacity: 1;
transition: opacity .12s ease-out;
}
.tooltip-inner {
line-height: 1;
padding: @ui-padding*.5 @ui-padding*.65;
border-radius: @component-border-radius;
background-color: @tooltip-background-color;
color: @tooltip-text-color;
white-space: nowrap;
max-width: none;
}
.keystroke {
font-size: max(1em, @ui-size*.85);
padding: .1em .4em;
margin: 0 @ui-padding*-.35 0 @ui-padding*.25;
border-radius: max(2px, @component-border-radius / 2);
color: @tooltip-text-key-color;
background: @tooltip-background-key-color;
}
&.top .tooltip-arrow {
border-top-color: @tooltip-background-color;
}
&.top-left .tooltip-arrow {
border-top-color: @tooltip-background-color;
}
&.top-right .tooltip-arrow {
border-top-color: @tooltip-background-color;
}
&.right .tooltip-arrow {
border-right-color: @tooltip-background-color;
}
&.left .tooltip-arrow {
border-left-color: @tooltip-background-color;
}
&.bottom .tooltip-arrow {
border-bottom-color: @tooltip-background-color;
}
&.bottom-left .tooltip-arrow {
border-bottom-color: @tooltip-background-color;
}
&.bottom-right .tooltip-arrow {
border-bottom-color: @tooltip-background-color;
}
}

View File

@@ -0,0 +1,85 @@
@tree-view-height: @ui-line-height;
.tree-view {
font-size: @ui-size;
background: @tree-view-background-color;
.project-root.project-root {
&:before {
height: @ui-tab-height;
background-clip: padding-box;
}
& > .header .name {
line-height: @ui-tab-height;
}
}
// Selected state
.selected:before {
background: @background-color-selected;
}
// Focus + selected state
&:focus {
.selected.list-item > .name, // files
.selected.list-nested-item > .list-item > .name, // folders
.selected.list-nested-item > .header:before { // arrow icon
color: contrast(@button-background-color-selected);
}
.selected:before {
background: @button-background-color-selected;
}
}
}
.theme-one-dark-ui .tree-view .project-root.project-root::before {
border-top: 1px solid transparent;
background-clip: padding-box;
}
.tree-view-resizer {
.tree-view-resize-handle {
width: 8px;
}
}
// Variable height, based on ems
.list-group li:not(.list-nested-item),
.list-tree li:not(.list-nested-item),
.list-group li.list-nested-item > .list-item,
.list-tree li.list-nested-item > .list-item {
line-height: @tree-view-height;
}
.list-group .selected::before,
.list-tree .selected::before {
height: @tree-view-height;
}
// icon
.list-group .icon,
.list-tree .icon {
display: inline-block;
height: inherit;
&::before {
top: initial;
line-height: inherit;
height: inherit;
vertical-align: top;
}
}
// Arrow icon
.list-group,
.list-tree {
.header.header.header.header::before {
top: initial;
line-height: inherit;
height: inherit;
vertical-align: top;
font-size: inherit;
}
}
.tree-view .project-root-header.project-root-header.project-root-header.project-root-header::before {
line-height: @ui-tab-height;
}

View File

@@ -0,0 +1,49 @@
// Pattern matching; ish is cray.
// http://lesscss.org/#-pattern-matching-and-guard-expressions
.text(normal) {
font-weight: normal;
color: @text-color;
}
.text(subtle) {
font-weight: normal;
color: @text-color-subtle;
}
.text(highlight) {
font-weight: normal;
color: @text-color-highlight;
}
.text(selected) {
.text(highlight)
}
.text(info) {
color: @text-color-info;
}
.text(success) {
color: @text-color-success;
}
.text(warning) {
color: @text-color-warning;
}
.text(error) {
color: @text-color-error;
}
.focus() {
outline: none;
border-color: @accent-color;
box-shadow: 0 0 0 1px @accent-color;
}
.valid() {
border-color: @text-color-success;
box-shadow: 0 0 0 1px @text-color-success;
background-color: mix(@text-color-success, @input-background-color, 10%);
}
.invalid() {
border-color: @text-color-error;
box-shadow: 0 0 0 1px @text-color-error;
background-color: mix(@text-color-error, @input-background-color, 10%);
}

View File

@@ -0,0 +1,132 @@
// ONE light UI variables
// ----------------------------------------------
@import "syntax-variables";
.ui-syntax-color() { @syntax-background-color: hsl(220,1%,98%); } .ui-syntax-color(); // fallback color
@ui-syntax-color: @syntax-background-color;
// Color guards -----------------
@ui-s-h: hue(@ui-syntax-color);
.ui-hue() when (@ui-s-h = 0) { @ui-hue: 220; } // Use blue hue when no saturation
.ui-hue() when (@ui-s-h > 0) { @ui-hue: @ui-s-h; }
.ui-hue();
@ui-saturation: min( saturation(@ui-syntax-color), 24%); // max saturation
@ui-lightness: max( lightness(@ui-syntax-color), 92%); // min lightness
// Main colors -----------------
@ui-fg: hsl(@ui-hue, @ui-saturation, @ui-lightness - 72%);
@ui-bg: hsl(@ui-hue, @ui-saturation, @ui-lightness); // normalized @syntax-background-color
@ui-border: darken(@level-3-color, 6%);
// Custom variables
// These variables are only used in this theme
// ----------------------------------------------
@ui-theme-name: one-light-ui;
// Text (Custom) -----------------
@text-color-faded: fade(@text-color, 30%);
@text-color-added: @text-color-success; // green
@text-color-ignored: @text-color-subtle; // faded
@text-color-modified: @text-color-warning; // orange
@text-color-removed: @text-color-error; // red
@text-color-renamed: @text-color-info; // blue
// Background (Custom) -----------------
@level-1-color: lighten(@base-background-color, 4%);
@level-2-color: @base-background-color;
@level-3-color: darken(@base-background-color, 6%);
@level-3-color-hover: darken(@level-3-color, 6%);
@level-3-color-active: darken(@level-3-color, 3%);
// Accent (Custom) -----------------
@accent-luma: luma( hsl(@ui-hue, 50%, 50%) ); // get lightness of current hue
// used for marker, inputs (smaller things)
@accent-color: mix( hsv( @ui-hue, 60%, 60%), hsl( @ui-hue, 100%, 68%), @accent-luma * 2 ); // mix hsv + hsl (favor hsl for dark, hsv for light colors)
@accent-text-color: contrast(@accent-color, hsl(@ui-hue,100%,16%), #fff, 40% );
// used for button, tooltip (larger things)
@accent-bg-color: mix( hsv( @ui-hue, 40%, 72%), hsl( @ui-hue, 100%, 66%), @accent-luma * 2 ); // mix hsv + hsl (favor hsl for dark, hsv for light colors)
@accent-bg-text-color: contrast(@accent-bg-color, hsl(@ui-hue,100%,10%), #fff, 40% );
// used for text only
@accent-only-text-color: mix( hsv( @ui-hue, 70%, 50%), hsl( @ui-hue, 100%, 60%), @accent-luma * 2 ); // mix hsv + hsl (favor hsl for dark, hsv for light colors)
// Components (Custom) -----------------
@badge-background-color: @background-color-selected;
@button-text-color-selected: @accent-bg-text-color;
@button-border-color-selected: @accent-color;
@checkbox-background-color: fade(@accent-bg-color, 33%);
@input-background-color-focus: hsl(@ui-hue, 100%, 96%);
@input-selection-color: mix( hsv( @ui-hue, 33%, 95%), hsl( @ui-hue, 100%, 98%), @accent-luma * 2 ); // mix hsv + hsl (favor hsl for dark, hsv for light colors)
@input-selection-color-focus: mix( hsv( @ui-hue, 44%, 90%), hsl( @ui-hue, 100%, 94%), @accent-luma * 2 ); // mix hsv + hsl (favor hsl for dark, hsv for light colors)
@overlay-backdrop-color: hsl(@ui-hue, @ui-saturation*0.4, @ui-lightness*0.8);
@overlay-backdrop-opacity: .66;
@progress-background-color: @accent-color;
@scrollbar-color: darken(@level-3-color, 14%);
@scrollbar-background-color: @level-3-color; // replaced `transparent` with a solid color to test https://github.com/atom/one-light-ui/issues/4
@scrollbar-color-editor: contrast(@ui-syntax-color, darken(@ui-syntax-color, 14%), lighten(@ui-syntax-color, 9%) );
@scrollbar-background-color-editor: @ui-syntax-color;
@tab-text-color: @text-color-subtle;
@tab-text-color-active: @text-color-highlight;
@tab-text-color-editor: contrast(@ui-syntax-color, lighten(@ui-syntax-color, 70%), @text-color-highlight );
@tab-background-color-editor: @ui-syntax-color;
@tab-inactive-status-added: fade(@text-color-success, 77%);
@tab-inactive-status-modified: fade(@text-color-warning, 77%);
@tooltip-background-color: @accent-bg-color;
@tooltip-text-color: @accent-bg-text-color;
@tooltip-text-key-color: @tooltip-background-color;
@tooltip-background-key-color: @tooltip-text-color;
// Sizes (Custom) -----------------
@ui-size: 1em;
@ui-input-size: @ui-size*1.15;
@ui-padding: @ui-size*1.5;
@ui-padding-pane: @ui-size*.5;
@ui-padding-icon: @ui-padding/3.3;
@ui-line-height: @ui-size*2;
@ui-tab-height: @ui-size*2.5;
// Packages variables
// These variables are used to override packages
// ----------------------------------------------
@settings-list-background-color: darken(@level-2-color, 3%);
@theme-config-box-shadow: inset 0 1px 2px hsla(0, 0%, 0%, .2), 0 1px 0 hsla(0, 0%, 100%, .3);
@theme-config-box-shadow-selected: inset 0 1px 3px hsla(0, 0%, 0%, .2);
@theme-config-border-selected: hsla(0, 0%, 0%, .5);
// Debug
// Output variables to the top of the UI
// -------------------------------------
// html:before {
// content: "@{variable}";
// }

Some files were not shown because too many files have changed in this diff Show More