Some Sass
Some Sass is a language server extension for Visual Studio Code. It brings improved code suggestions, documentation and code navigation for SCSS.
Some features include:
- Full support for
@use
and@forward
, including aliases, prefixes and hiding. - Workspace-wide code navigation and refactoring, such as Rename Symbol.
- Rich documentation through SassDoc.
- Language features for
%placeholders
, both when using them and writing them.
Get the extension
You can find the extension here:
- On the Visual Studio Code Marketplace.
- On the Open VSX Registry.
- In the Releases section on GitHub.
See the User guide section to learn more about what the extension can do.
Some Sass Language Server
Some Sass is also a language server using the Language Server Protocol (LSP).
The language server is published on npm, and can be used with any editor that has an LSP client. See Getting started to learn more.
Navigating the docs
To navigate between pages you can click the arrow buttons, press the left and right arrow keys on your keyboard, or use the sidebar menu.
To search click the magnifying class icon to the top left or press s
on your keyboard.
IntelliSense
This page describes what Some Sass adds to code completions, also called IntelliSense in Visual Studio Code.
Namespaced suggestions
With the recommended settings, suggestions get limited to only the symbols available in that namespace. Code completions from Some Sass has full support for:
- aliasing (
@use "foo" as f;
) - prefixes (
@forward "foo" as bar-*;
) - hide/show
Sass built-in modules (such as "sass:map"
) get the same treatment when imported with @use
.
SassDoc block
Some Sass works best when you document your codebase with SassDoc. To make it easier you can let Some Sass generate a skeleton by typing ///
and choosing SassDoc block.
SassDoc string literal union types
If you have a function or mixin that expects only a set of string values you can document them with a string literal union type. Some Sass will present the list of choices when you use them.
/// Get a timing value for use in animations.
/// @param {"sonic" | "link" | "homer" | "snorlax"} $mode - The timing you want
/// @return {String} - the timing value in ms
@function timing($mode) {
@if map.has-key($_timings, $mode) {
@return map.get($_timings, $mode);
} @else {
@error 'Unable to find a mode for #{$mode}';
}
}
Signature helpers
For functions and mixins, Some Sass gives you signature helpers. These are small popups that show information about the mixin or function's parameters, and which one you are about to enter.
Placeholder selectors
There are two ways which Some Sass helps with code suggestions for placeholder selectors:
%placeholder
-first workflows@extend
-first workflows
Placeholder first
This is where you write a placeholder selector first, and then @extend
it somewhere else in your code. Some Sass will suggest all available placeholder selectors when you type @extend %
.
Extend first
This workflow can be useful in scenarios where the selectors change, but the style should stay the same. You define a stylesheet with the selectors, @extend
stable placeholder selectors, and then implement those placeholders. This workflow is for instance used in parts of the Discord theming community.
Import suggestions
When you write imports Some Sass reads the file system to help you complete the string.
pkg:
imports
You can get a list of packages in the closest node_modules
folder by manually triggering IntelliSense (Ctrl + Space) to help you write pkg:
imports.
Navigation
This document describes the navigation features of Some Sass.
Go to definition
To use this feature, either:
- Hold down
Cmd
/Ctrl
and click a symbol. - Right-click a symbol and choose Go to Definition.
- Press
F12
when the cursor is at a symbol.
Find references
To use this feature, either:
- Right-click a symbol and choose Find all references.
- Press
Shift
+Alt
/Opt
+F12
when the cursor is at a symbol.
Find all references reference.
Go to symbol
To use this feature, open the Go menu and choos either:
- Go to symbol in Editor
- Go to symbol in Workspace
Hover info
This document describes the hover information given by Some Sass.
Symbol information
When you hover over a symbol Some Sass shows a preview of the declaration and the name of the file where it is declared. Things get more interesting when you add SassDoc though.
SassDoc documentation
If a symbol is documented with SassDoc, the documentation is shown in the hover information like how you might see JSDoc. This is especially helpful if you have a core set of utility functions and mixins, or if you use a Sass library provided by a third party.
/// Calculate a responsive size value relative to a given screen size
/// Will return a CSS rule that corresponds to the given pixel size at
/// the given screen size and scales with changes in screen size
/// @param {Number} $px-size - Size to calculate from, in px without unit
/// @param {Number} $screen-width - Screen width to calculate from, in px without unit, default 1400
/// @param {Number} $screen-height - Screen height to calculate from, in px without unit, default 900
/// @return {Number} - Input expressed as a responsive value
@function relative-size($px-size, $screen-width: 1400, $screen-height: 900) {
// ...
}
Sass built-ins
Hover information for Sass built-ins include links to the reference documentation.
SassDoc annotations
Hover information for Sassdoc annotations link to the reference documentation.
Refactoring
This document describes the refactoring features of Some Sass.
Rename symbol
With Some Sass installed you can rename a symbol and it is renamed across the whole workspace.
Extract
Some Sass adds code actions to extract a selection to a variable, function or mixin.
Diagnostics
This document describes the diagnostics features of Some Sass.
Deprecated symbols
Symbols documented as @deprecated
with SassDoc is shown
with a strikethrough.
Color decorators
This document describes the color decorators features of Some Sass.
Decorators for Sass variables
Some Sass adds decorators for color variables where they are used.
Settings
This document describes the settings available in Some Sass.
Recommended settings
These are the recommended settings:
{
// Recommended if you don't rely on @import
"somesass.suggestOnlyFromUse": true,
// Optional, if you get suggestions from the current document after namespace.$ (you don't need the $ for narrowing down suggestions)
"editor.wordBasedSuggestions": false,
// Optional, for Vue, Svelte, Astro: add `scss` to the list of excluded languages for Emmet to avoid suggestions in Vue, Svelte or Astro files.
// VS Code understands that <style lang="scss">`blocks are SCSS, and so won't show Emmet suggestions in that block.
"emmet.excludeLanguages": [
// Markdown is excluded by default in VS Code
"markdown",
"scss",
],
}
About word-based suggestions
When you get completion suggestions and type namespace.$
, Visual Studio Code treats $
as a fresh start for suggestions. It will start matching any variable in the current document. There are two ways to get around this:
- Turn off word-based suggestions by setting
"editor.wordBasedSuggestions": false
. - Don't type the
$
when you write the variable name, let completions fill it out for you.
With the second approach you can keep word-based suggestions turned on.
Settings reference
These are the settings you can use to tune Some Sass.
Code suggestion
Only include suggestions from used modules
If your project is on the modern module syntax (@use
and @forward
instead of @import
), you may want to turn
on this setting.
With this setting turned on, Some Sass will only suggest variables, mixins and functions from the namespaces that are
in use in the open document. This setting will be turned on by default at some point after @import
becomes CSS-only.
- JSON key:
somesass.suggestOnlyFromUse
. - Default value:
false
.
Suggest variables, mixins, and functions from the open document
Visual Studio Code has built-in suggestions for variables, mixins and functions created in the open document.
By default Some Sass will not send suggestions for the same symbols. If you prefer the suggestions from Some Sass (for instance if you use SassDoc), you can opt in by turning on this setting. There will unfortunately be duplicates.
- JSON key:
somesass.suggestAllFromOpenDocument
- Default value:
false
.
Suggestion style
Mixins with @content
SassDoc annotations and %placeholders
get two suggestions by default:
- One without
{ }
. - One with
{ }
. This one creates a new block, and moves the cursor inside the block.
If you find this noisy, you can control which suggestions you would like to see:
- All suggestions (default).
- No brackets.
- Only brackets. This still includes other suggestions, where there are no brackets to begin with.
Decide when function suggestions should kick in
Suggest functions after the specified symbols when in a string context.
For example, if you add the /
symbol to this setting, then background: url(images/he|)
could suggest a hello()
function (|
in this case indicates cursor position).
- JSON key:
somesass.suggestFunctionsInStringContextAfterSymbols
. - Default value:
" (+-*%"
.
Workspace scanner
Exclude files or folders
List of micromatch patterns for directories that are excluded when scanning.
- JSON key:
somesass.scannerExclude
. - Default value:
["**/.git/**", "**/node_modules/**", "**/bower_components/**"]
.
Adjust scanner depth
Depending on your project size, you may want to tweak this setting to control how many files are included.
- JSON key:
somesass.scannerDepth
. - Default:
30
.
Stop scanner from following links
@deprecated
If you don't want Some Sass to follow @import
, @use
or @forward
links you can turn this setting off.
This will limit functionality, and is not recommended. This setting will be removed at some point
after @import
becomes CSS-only.
- JSON key:
somesass.scanImportedFiles
. - Default:
true
.
Use Some Sass outside Visual Studio Code
Some Sass is a language server using the Language Server Protocol (LSP).
The language server is published independently to npm, and can be used with any editor that has an LSP client. The server is designed to run alongside the VS Code CSS language server.
Getting started
You can install the language server with npm
:
npm install --global some-sass-language-server
Then start the language server like so:
some-sass-language-server --stdio
Options
--debug
โ runs the development build of the language server, helpful to get more context if the server crashes
Settings
The language server requests settings via workspace/configuration
on the somesass
key. All fields are optional.
Configure a client
The next step is to configure a language client.
Configure a client
An editor needs a language client for the Language Server Protocol (LSP) to use a language server.
To configure a client for an editor that doesn't have one yet, check the documentation for your editor to see if it supports LSP natively. If not, there may be an extension, add-on or plugin that adds support for LSP.
Existing clients
This list of language client implementations may be a helpful starting point. You may also want to look at existing clients.
Existing clients
Editors with ready-configured clients, maintained by the community.
Neovim
Neovim has a ready-to-use client configuration maintained by the community.
There are two options:
New contributors
Thank you for showing an interest in contributing ๐
If you've never worked on Some Sass you're in the right place. There are several ways you can help.
- Share your setup in Discussions' Show and tell.
- Research open issues to find out what needs to be done.
- Configure language clients for more editors.
- Improve this documentation, add screenshots or recordings.
- Add unit tests or end-to-end tests where missing.
- Volunteer to fix bugs or add missing features.
Have a look at Writing documentation if you want to work on the docs.
Diving in to code? You may be interested in:
- Primers on extensions for Visual Studio Code and the Language Server Protocol
- How you set up your development environment.
- Before long you'll need to do some debugging.
Extensions for Visual Studio Code
This is not required reading, but if you want to learn more about extension development these links are a good place to start.
Some Sass is a language server extension. It can also run in the browser. The project has automated end-to-end tests for both Electron and the browser.
Language Server Protocol
From Why Language Server?:
[The] Language Server Protocol [...] standardizes the communication between language tooling and code editor. This way [...] any LSP-compliant language toolings can integrate with multiple LSP-compliant code editors, and any LSP-compliant code editors can easily pick up multiple LSP-compliant language toolings. LSP is a win for both language tooling providers and code editor vendors!
In other words, LSP lets you build the language support tools once and run in any editor that has an LSP client.
For the most part you don't need to worry about the implementation details of the LSP. Microsoft's TypeScript implementation handles the nitty-gritty.
Language features
The Visual Studio Code documentation for Programatic language features gives a good sense of what's possible with LSP. If you want to dive deep, the specification lists all the messages and their parameters.
Development environment
The language server is written in TypeScript and runs both in Node and the browser. While the server can be used outside of Visual Studio Code, it's recommended to use VS Code for development.
You need:
- A long-term support version of Node.js
- Visual Studio Code
Recommended extensions:
- Vitest to help run and debug individual tests.
To preview the documentation you need mdbook. If you're on macOS and use Homebrew you can brew install mdbook
.
Getting started
Clone the repo and install dependencies:
git clone git@github.com:wkillerud/some-sass.git
cd some-sass
npm install
Run the build and automated tests. Some of the automated tests open a new window and run in Visual Studio Code Insiders.
npm run build
npm run test:all
Watch mode
You can have nx
watch the workspace for changes and rerun a minimum build:
npm run dev
Some packages have watch mode for unit tests using Vitest:
packages/language-server/
packages/language-services/
In packages with Vitest you start watch mode with the test
script:
npm test
Next steps
You may want to have a look at the architecture of the language server. Most of the functionality of the language server is in the language-services
package in packages/
.
Test-driven development with Vitest and the VS Code debugger gives the shortest feedback loop.
Architecture
Being a language server extension, Some Sass consists of a client and a server. The client starts the server when it opens a file with SCSS. This is called activation.
From there everything happens via messages.
Some Sass also works with Visual Studio Code in the browser. It works more or less the same as the regular Node version, except it doesn't have direct access to the file system.
To work around this, the server makes requests to the client, which then uses the FileSystem API to work with files and directories, before sending the result back to the server.
Server architecture
The code for the server is divided in three packages:
- Language server
- Language services
- VS Code CSS language service โย the SCSS parser and language features that are included in VS Code.
Language server
This package handles communication with the language client, and not much else.
Language services
This is where you find the functionality of the language server, organized in classes that inherit from a base LanguageFeature
class.
All features will parse the given document, but parses are cached for performance reasons. The flow looks something like this:
A language feature takes a text document and will try to get a data structure representing the document's Sass semantics such as variables, classes, functions and mixins.
The first time this happens the document gets sent to the parser, which returns this data structure. That result is cached. The next time a feature tries to get the data structure it will read from the cache. The cache entry is removed when the document changes so the new document can be parsed.
In addition to the parsed document, the cache also holds:
- The results from resolving links (
@use
,@forward
,@import
). - The results from parsing the document's Sassdoc.
- The document's symbols, as returned from
findDocumentSymbols()
.
VS Code CSS language service
The project includes a private fork of the vscode-css-languageservice
module. The original vscode-css-languageservice
powers the CSS, SCSS and Less features in Visual Studio Code. Some Sass uses this module's parser and some of its language features. It's kept as a separate package to simplify updates, and to make it easier to send patches upstream.
Building
This document describes how to build Some Sass.
The workspace
This repo is an npm
workspace with several packages listed in the "workspaces"
key in the root package.json
. The packages are listed in order with the "base" package at the top and the published language server and extension toward the bottom.
A full build
Run this command at the root level of the repo to build all packages:
npm run build
This will build all packages and the Visual Studio Code extension.
Partial builds
Each package has its own build
command. If you made a change in the language-server
folder you only have to build that and the vscode-extension
packages. Of course you can allways do a full build if you want.
Clean builds
If something unexpected happens with your build you can do a clean build:
npm run clean
npm run build
This deletes any old build you may have before doing a new build.
Automated tests
This document describes how to run the automated tests and what the different tests cover.
Unit tests
All packages in packages/
have unit tests. To run them:
npm run test
The main test runner is Vitest. vscode-css-languageservice
uses Mocha.
Unit tests typically cover either a utility function or a language feature such as doHover
. For language features the tests are typically split in several files, each focusing on part of the functionality of the language feature.
End-to-end tests
The Visual Studio Code extension includes end-to-end tests. To run them:
npm run test:e2e
It also includes end-to-end tests for the web extension. To run them:
npm run test:web
The end-to-end tests have some overlap with the unit tests for language features, but are useful to confirm the communication between client and server works as expected.
Run all tests
A convenience script lets you run all unit tests and end-to-end tests:
npm run test:all
Test coverage
While there's no target for test coverage in the project, coverage reports can be useful to see if there's a corner case that should be tested.
Generate a coverage report
Coverage reports are generated per package. To generate a report run:
npm run coverage
Coverage reports are printed to the terminal. HTML versions you can open in a browser get generated in each package's directory. Look for a coverage/
folder and open index.html
in your browser.
Debugging
This page assumes you're using Visual Studio Code as the debugger. Go to the Run and Debug pane in VS Code to find the different launch configurations.
- Launch extension
- Launch web extension
- Launch integration tests
- Launch web integration tests
Launch extension
This opens a new window of Visual Studio Code running as a local extension host. Open the Sass project you're using to test in the extension host window. If you don't have one you can open the folder vscode-extension/test/fixtures/
in this repository.
Set breakpoints
Find node-server.js
in the vscode-extension/dist/
folder to set breakpoints. A good place to start is to search for the request handlers in server.ts
like onCompletion
and onHover
.
Restart the debugger after building to see any changes you make in the code.
See log output
You'll find the log output in two places:
- The Debug console in the window where you started the debugger.
- The Output pane in the extension host (pick Some Sass from the dropdown).
Launch web extension
This opens a new window of Visual Studio Code running as a web extension host. Open the Sass project you're using to test in the extension host window. If you don't have one you can open the folder vscode-extension/test/fixtures/
in this repository.
Find browser-server.js
in the vscode-extension/dist/
folder to set breakpoints.
Restart the debugger after building to see any changes you make in the code.
Debugging in the browser
You can use Some Sass with Visual Studio Code running in the browser. This document describes how you can test Some Sass running in Chromium.
Run the test command
In a terminal, run:
npm run start:web
This opens Visual Studio Code running as a web extension host in Chromium. The language server runs as a web worker, and is started when you open a Sass file.
Open the Sass project you're using to test in the extension host window. If you don't have one you can open the folder vscode-extension/test/fixtures/
in this repository.
Navigating the Chromium developer tools
Open the developer tools and click the Sources tab to set breakpoints.
The web worker for browser-server.js
is in the left panel of the Sources tab. If you don't see it, make sure you open a Sass file to activate the extension.
In the WorkerExtensionHost you'll see localhost:3000
and serverExportVar
. You may find it easier to navigate in severExportVar
since it uses source maps to match the source code of the language server package.
Debugging unit tests
This document assumes you use Visual Studio Code and have the Vitest extension.
Open a unit test file (excluding tests in vscode-css-languageservice
, which use Mocha) and find the test you want to debug.
You should see an icon in the gutter. To debug the test, right click and select Debug test.
Test-driven development
When you work on a language feature it's useful to set up a test and use that while developing.
The tests have an in-memory file system provider, so you can test how a language feature works with Sass code without making files on disk.
By using the Vitest debugger you can shorten the feedback loop significantly compared to building the whole project and testing manually in Visual Studio Code.
Debugging end-to-end tests
End-to-end tests run in Visual Studio Code and are helpful to ensure the user experience is as we expect. However, they can be tricky to write sometimes. This document describes how you can debug the tests themselves.
Prepare Visual Studio Code
The debugger runs tests in your version of Visual Studio Code, not VS Code insiders like when running the tests from the command line. You need to use the default settings for Some Sass (use the included workspace settings from the repo).
Launch the debugger
Go to the Run and Debug pane in VS Code and run Launch integration tests. The tests will start running immediately, and the window closes when the test run is finished.
You can set breakpoints directly in the test code in vscode-extension/test/e2e/
.
Releasing new versions
This document describes how to release a new version of Some Sass.
Conventional Commits
This repository uses nx to manage release
- The language service package is published to
npm
. - The Visual Studio Code extension is published to:
nx reads conventional commits to determine what the new versions should be, and to generate changelogs. Which version is released depends on how you write the commit message.
Commit message | Release type |
---|---|
docs: add guide for configuring sublime | No new release. |
fix: update css-languageservice | Patch. Bugfix release, updates for runtime dependencies. |
feat: add support for show keyword in forward | Minor. New feature release. |
refactor: remove reduntant options for latest language version BREAKING CHANGE: The scanImportedFiles option has been removed. | Major. Breaking release, like removing an option or changing engines version. (Note that the BREAKING CHANGE: token must be in the footer of the commit) |
Release process
To start a new release:
- Get the latest
main
branch withgit checkout main && git pull
. - Run
npx nx release --skip-publish
. - Push the changes and tags with
git push && git push --tags
.
GitHub Actions is configured to do the actual publishing when there are new tags.
Manual fallback
For npm
packages:
npm version [major|minor|patch]
npm publish
For the VS Code extension:
vsce package
Then publish manually via Visual Studio Marketplace, Open VSX and GitHub Releases (attach the .vsix
file to the release).
References:
Writing documentation
Help others get the most out of their software by contributing to documentation.
- Do you have a pro tip you want to share?
- Did you take a screenshot that can help visualize something?
New contributors are especially welcome to write documentation and add examples. As a new contributor you know best what is confusing or difficult.
Quick start
Fork and clone the repository from GitHub. The documentation is in the docs/src/
folder.
git clone git@github.com:wkillerud/some-sass.git
Once you're happy, commit the changes and prefix the commit message with docs:
git commit -m "docs: add GIF demoing Go to definition"
Preview the documentation
You need mdbook to preview the documentation on your machine.
If you're on macOS and use Homebrew you can brew install mdbook
. Otherwise, check the mdbook user guide.
Once you have it installed, open a terminal and navigate to the docs/
directory.
cd docs
mdbook serve --open
Changes you make in Markdown files in docs/src/
are live updated in the browser.
Who we are writing for
We write for three different groups:
- Stylesheet developers who use Some Sass
- Users of editors other than Visual Studio Code who want to use Some Sass
- Developers who want to fix a bug or add to Some Sass
Each group should find sections and chapters in the sidebar to help guide them to what they are looking for.
Writing for stylesheet developers
A stylesheet developer doesn't need to learn about the inner workings of Some Sass. They are here to learn what the tool can do, or because something is not matching their expectations.
Introduce the reader to recommended settings early, including settings for the editor itself.
Screenshots and recordings
Show what you explained in writing using one or more screenshots if you can. Media should come after the paragraph explaining a feature.
If something is better conveyed in a screen recording, prefer an image format like GIF over video. Recordings should be short and showcase one thing. The quality must be good enough that text is legible. For an example, see the IntelliSense documentation in Visual Studio Code.
Writing for users of editors other than Visual Studio Code
Users of editors other than Visual Studio Code who want to use Some Sass need to know:
- That it's possible to do so
- How to do it
Assume the reader is new to the language server protocol and has never configured a language server client. Examples are a great help here.
Writing for developers who want to change or add to Some Sass
Here we need to consider both new and returning developers.
Onboarding
For new developers:
- Assume the reader has never written an extension for Visual Studio Code.
- Assume the reader is new to the Language Server Protocol.
Introduce new contributors to these topics, and link to external material if they want to learn more. Also introduce the architecture so they have a better idea of where to start. Visualize with diagrams.
Explain how they should set up their development environment to be productive.
Guides
All developers (including your future self) could use a guide for common tasks like testing and debugging. This documentation can assume the reader completed the onboarding.
Writing style guide
These are more guidelines than actual rules.
- The first time you reference Visual Studio Code below a heading, write out the full name. After that you can use VS Code.
- Prefer Excalidraw for diagrams, exported as PNG and included in Markdown as an image.
The Hemingway Editor is a free tool to help edit your writing. You can also refer to these notes from Google Technical Writing One if you'd like. That said, don't worry too much about the details.