Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: stylus/stylus
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.59.0
Choose a base ref
...
head repository: stylus/stylus
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0.60.0
Choose a head ref

Commits on Aug 30, 2022

  1. chore: update funding.yml config (#2718)

    Github official approved for stylus github sponsor
    iChenLei authored Aug 30, 2022
    Copy the full SHA
    10eece0 View commit details

Commits on Sep 11, 2022

  1. docs: new stylus-lang.com (#2695)

    * docs: new stylus-lang.com
    
    * chore: replace website title
    
    * chore: http convert to https and netlify badge
    
    * chore: disable algolia temporarily
    
    * feat: add try.html
    
    * feat: add google ga
    iChenLei authored Sep 11, 2022
    Copy the full SHA
    ae16898 View commit details
  2. chore(deps): bump undici from 5.4.0 to 5.10.0 in /docs (#2721)

    Bumps [undici](https://github.com/nodejs/undici) from 5.4.0 to 5.10.0.
    - [Release notes](https://github.com/nodejs/undici/releases)
    - [Commits](nodejs/undici@v5.4.0...v5.10.0)
    
    ---
    updated-dependencies:
    - dependency-name: undici
      dependency-type: indirect
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Sep 11, 2022
    Copy the full SHA
    e1baeba View commit details
  3. chore(deps): bump vite from 2.9.9 to 2.9.15 in /docs (#2722)

    Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 2.9.9 to 2.9.15.
    - [Release notes](https://github.com/vitejs/vite/releases)
    - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
    - [Commits](https://github.com/vitejs/vite/commits/v2.9.15/packages/vite)
    
    ---
    updated-dependencies:
    - dependency-name: vite
      dependency-type: indirect
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Sep 11, 2022
    Copy the full SHA
    3ec65f9 View commit details
  4. chore(deps): bump terser from 5.14.0 to 5.15.0 in /docs (#2720)

    Bumps [terser](https://github.com/terser/terser) from 5.14.0 to 5.15.0.
    - [Release notes](https://github.com/terser/terser/releases)
    - [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
    - [Commits](terser/terser@v5.14.0...v5.15.0)
    
    ---
    updated-dependencies:
    - dependency-name: terser
      dependency-type: indirect
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Sep 11, 2022
    Copy the full SHA
    d30e744 View commit details
  5. Copy the full SHA
    8284265 View commit details

Commits on Sep 14, 2022

  1. Copy the full SHA
    1c6b4a6 View commit details

Commits on Sep 21, 2022

  1. use https instead of http where supported (#2725)

    * use https instead of http where supported
    
    * update domains, paths and query strings to what currently works
    
    * use ? instead of # in the URL
    lpmi-13 authored Sep 21, 2022
    Copy the full SHA
    2a5ca6b View commit details

Commits on Oct 10, 2022

  1. Copy the full SHA
    1a85088 View commit details

Commits on Feb 17, 2023

  1. chore(deps): bump undici from 5.10.0 to 5.19.1 in /docs (#2758)

    Bumps [undici](https://github.com/nodejs/undici) from 5.10.0 to 5.19.1.
    - [Release notes](https://github.com/nodejs/undici/releases)
    - [Commits](nodejs/undici@v5.10.0...v5.19.1)
    
    ---
    updated-dependencies:
    - dependency-name: undici
      dependency-type: indirect
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Feb 17, 2023

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    040d618 View commit details

Commits on Mar 1, 2023

  1. ci: update nodejs matrix test suites (#2765)

    * ci: update nodejs matrix test suite
    
    * Update ci.yml
    iChenLei authored Mar 1, 2023

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    ceac097 View commit details

Commits on Mar 5, 2023

  1. Correct typos and copy edit (#2764)

    Fix capitalization of Node.js, CSS, Stylus (CSS is already plural so CSSs is not really correct)
    
    Correct minor language errors
    peterhauke authored Mar 5, 2023
    Copy the full SHA
    e8ea8ca View commit details

Commits on Mar 30, 2023

  1. Copy the full SHA
    5ed3ea7 View commit details

Commits on Apr 3, 2023

  1. add support for CSS Values 4 viewport-relative units (#2775)

    Co-authored-by: Taras Polovyi <taras.polovyi@grammarly.com>
    taraspolovyi and tpolovyi-gr authored Apr 3, 2023
    Copy the full SHA
    1d2eaa3 View commit details

Commits on Apr 6, 2023

  1. Copy the full SHA
    8833fe4 View commit details
  2. chore(deps): bump json5 from 2.2.1 to 2.2.3 in /docs (#2747)

    Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3.
    - [Release notes](https://github.com/json5/json5/releases)
    - [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
    - [Commits](json5/json5@v2.2.1...v2.2.3)
    
    ---
    updated-dependencies:
    - dependency-name: json5
      dependency-type: indirect
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 6, 2023
    Copy the full SHA
    73708f3 View commit details

Commits on May 11, 2023

  1. Copy the full SHA
    21f048d View commit details

Commits on Jun 6, 2023

  1. chore(deps): bump vite from 2.9.15 to 2.9.16 in /docs (#2799)

    Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 2.9.15 to 2.9.16.
    - [Release notes](https://github.com/vitejs/vite/releases)
    - [Changelog](https://github.com/vitejs/vite/blob/v2.9.16/packages/vite/CHANGELOG.md)
    - [Commits](https://github.com/vitejs/vite/commits/v2.9.16/packages/vite)
    
    ---
    updated-dependencies:
    - dependency-name: vite
      dependency-type: indirect
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Jun 6, 2023
    Copy the full SHA
    41fd9c3 View commit details

Commits on Aug 11, 2023

  1. chore(deps): bump @antfu/utils, unocss and unplugin-vue-components (#…

    …2797)
    
    Bumps [@antfu/utils](https://github.com/antfu/utils) to 0.7.4 and updates ancestor dependencies [@antfu/utils](https://github.com/antfu/utils), [unocss](https://github.com/unocss/unocss) and [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components). These dependencies need to be updated together.
    
    
    Updates `@antfu/utils` from 0.5.2 to 0.7.4
    - [Release notes](https://github.com/antfu/utils/releases)
    - [Commits](antfu/utils@v0.5.2...v0.7.4)
    
    Updates `unocss` from 0.36.0 to 0.52.7
    - [Release notes](https://github.com/unocss/unocss/releases)
    - [Commits](unocss/unocss@v0.36.0...v0.52.7)
    
    Updates `unplugin-vue-components` from 0.19.6 to 0.25.0
    - [Release notes](https://github.com/antfu/unplugin-vue-components/releases)
    - [Commits](unplugin/unplugin-vue-components@v0.19.6...v0.25.0)
    
    ---
    updated-dependencies:
    - dependency-name: "@antfu/utils"
      dependency-type: indirect
    - dependency-name: unocss
      dependency-type: direct:development
    - dependency-name: unplugin-vue-components
      dependency-type: direct:development
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Aug 11, 2023
    Copy the full SHA
    00ca9fe View commit details

Commits on Aug 30, 2023

  1. Classes (#2813)

    * use classes in errors
    
    * use classes in lib/renderer
    
    * use classes in lib/arguments
    
    * remove double initializer
    
    * use classes in lib/nodes/atblock
    
    * fix constructor jsdoc in wrong place
    
    * convert atrule and subclasses to use classes
    
    * use classes in lib/node
    
    * use classes in lib/nodes/boolean
    
    * use classes in lib/nodes/ident
    
    * use classes in lib/nodes/expression
    
    * fix getter typed as function
    
    * use classes in lib/nodes/rgba
    
    * use classes in lib/nodes/call
    
    * use classes in lib/nodes/group
    
    * use classes in lib/nodes/literal
    
    * use class in lib/nodes/selector
    
    * use class in lib/nodes/block
    
    * use class in lib/nodes/property
    
    * use class in lib/nodes/unit
    
    * use class in lib/nodes/binop
    
    * use class in lib/nodes/function
    
    * use class in lib/nodes/string
    
    * use class in lib/nodes/import
    
    * fix expression getters written as functions
    
    * use class in lib/nodes/param
    
    * use class in lib/nodes/if
    
    * use class in lib/nodes/ternary
    
    * use class in lib/nodes/each
    
    * use class in lib/nodes/unaryop
    
    * use class in lib/nodes/object
    
    * use class in lib/nodes/extend
    
    * use classes in lib/nodes/hsla
    
    * fix hsla/rgba fromRGBA/fromHSLA static constructors
    
    * fix trying to initialize boolean without `new`
    
    * use class in lib/nodes/member
    
    * use class in lib/nodes/comment
    
    * use class in lib/nodes/namespace
    
    * use class in lib/nodes/query-list
    
    * use class in lib/nodes/query
    
    * use class in lib/nodes/feature
    
    * fix CoercionError not calling super
    
    * fix trying to construct a class without `new`
    
    * use class in lib/nodes/charset
    
    * use class in lib/nodes/null
    
    * use class in lib/nodes/return
    
    * fix events not getting exported
    
    * use class in lib/nodes/root
    
    * use class in lib/stack
    
    * use classes in `Visitor` and it's subclasses
    
    * use classes in lib/visitor/deps-resolver
    
    * use classes in lib/lexer
    
    * use class in selector parser
    
    * use classes in Converter
    
    * use classes in MemoryCache
    
    * use classes in FSCache
    
    * use classes in NullCache
    
    * use classes in lib/functions/image
    
    * use classes in lib/token
    
    * use class in lib/stack/scope
    
    * use class in lib/stack/frame
    
    * use class in lib/parser
    
    * use `super.method()`
    
    instead of `Node.prototype.method.call(this, ...args)`
    
    * use `Object.setPrototypeOf` instead of `__proto__`
    
    * use static method instead of initialisor (for node v10-12)
    
    * use getters to use alias
    
    property assignment doesn't work on node v10-12
    
    * added deno tests
    
    * downgrade `@adobe/css-tools` to 4.2.0 for node v10 compat
    vixalien authored Aug 30, 2023
    Copy the full SHA
    50b0a33 View commit details
  2. chore: minor change (#2815)

    iChenLei authored Aug 30, 2023
    Copy the full SHA
    74efabf View commit details
  3. 0.60.0 (#2816)

    iChenLei authored Aug 30, 2023
    Copy the full SHA
    d20dc76 View commit details
Showing with 19,799 additions and 12,662 deletions.
  1. +1 −1 .github/FUNDING.yml
  2. +0 −4 .github/PULL_REQUEST_TEMPLATE.md
  3. +23 −3 .github/workflows/ci.yml
  4. +4 −0 Changelog.md
  5. +0 −4 Readme.md
  6. +7 −7 bin/stylus
  7. +33 −0 deno/test.ts
  8. +7 −0 docs/.gitignore
  9. +13 −0 docs/.vitepress/components.d.ts
  10. +15 −0 docs/.vitepress/components/HomePage.vue
  11. +34 −0 docs/.vitepress/components/Runkit.vue
  12. +273 −0 docs/.vitepress/config.ts
  13. +29 −0 docs/.vitepress/meta.ts
  14. +93 −0 docs/.vitepress/scripts/assets.ts
  15. +33 −0 docs/.vitepress/style/main.css
  16. +89 −0 docs/.vitepress/style/vars.css
  17. +24 −0 docs/.vitepress/theme/index.ts
  18. +3 −0 docs/.vitepress/theme/pwa.ts
  19. +0 −57 docs/atrules.md
  20. +0 −1,287 docs/bifs.md
  21. +0 −39 docs/comments.md
  22. +0 −111 docs/conditionals.md
  23. +0 −103 docs/css-style.md
  24. +64 −0 docs/docs/atrules.md
  25. +1,481 −0 docs/docs/bifs.md
  26. +21 −13 docs/{ → docs}/block.md
  27. +42 −0 docs/docs/comments.md
  28. 0 docs/{ → docs}/compare.md
  29. +124 −0 docs/docs/conditionals.md
  30. +111 −0 docs/docs/css-style.md
  31. +68 −0 docs/docs/error-reporting.md
  32. +40 −0 docs/docs/escape.md
  33. +309 −0 docs/docs/executable.md
  34. +224 −0 docs/docs/extend.md
  35. +67 −0 docs/docs/firebug.md
  36. +31 −0 docs/docs/font-face.md
  37. +283 −0 docs/docs/functions.md
  38. +35 −26 docs/{ → docs}/functions.url.md
  39. +39 −0 docs/docs/gedit.md
  40. +206 −0 docs/docs/hashes.md
  41. +91 −68 docs/{ → docs}/import.md
  42. +157 −0 docs/docs/index.md
  43. +86 −0 docs/docs/interpolation.md
  44. +46 −0 docs/docs/introspection.md
  45. +157 −0 docs/docs/iteration.md
  46. +227 −0 docs/docs/js.md
  47. +125 −0 docs/docs/keyframes.md
  48. +45 −0 docs/docs/kwargs.md
  49. +172 −151 docs/{ → docs}/lists.md
  50. +26 −0 docs/docs/literal.md
  51. +137 −0 docs/docs/media.md
  52. +81 −0 docs/docs/middleware.md
  53. +217 −0 docs/docs/mixins.md
  54. +599 −0 docs/docs/operators.md
  55. +245 −173 docs/{ → docs}/selectors.md
  56. +44 −0 docs/docs/sourcemaps.md
  57. 0 docs/{ → docs}/textmate.md
  58. +103 −0 docs/docs/vargs.md
  59. +117 −0 docs/docs/variables.md
  60. +0 −60 docs/error-reporting.md
  61. +0 −33 docs/escape.md
  62. +0 −238 docs/executable.md
  63. +0 −203 docs/extend.md
  64. +0 −63 docs/firebug.md
  65. +0 −30 docs/font-face.md
  66. +0 −243 docs/functions.md
  67. +0 −33 docs/gedit.md
  68. +0 −177 docs/hashes.md
  69. +38 −0 docs/index.md
  70. +0 −74 docs/interpolation.md
  71. +0 −42 docs/introspection.md
  72. +0 −132 docs/iteration.md
  73. +0 −200 docs/js.md
  74. +0 −113 docs/keyframes.md
  75. +0 −38 docs/kwargs.md
  76. +0 −23 docs/literal.md
  77. +0 −117 docs/media.md
  78. +0 −72 docs/middleware.md
  79. +0 −187 docs/mixins.md
  80. +0 −520 docs/operators.md
  81. +5,429 −0 docs/package-lock.json
  82. +27 −0 docs/package.json
  83. BIN docs/public/favicon.ico
  84. +1 −0 docs/public/logo.svg
  85. BIN docs/public/op.png
  86. +2 −0 docs/public/robots.txt
  87. BIN docs/public/stylus.png
  88. +0 −39 docs/sourcemaps.md
  89. +9 −0 docs/try.md
  90. +31 −0 docs/tsconfig.json
  91. +0 −88 docs/vargs.md
  92. +0 −99 docs/variables.md
  93. +132 −0 docs/vite.config.ts
  94. +63 −59 lib/cache/fs.js
  95. +107 −105 lib/cache/memory.js
  96. +47 −46 lib/cache/null.js
  97. +303 −300 lib/convert/css.js
  98. +19 −25 lib/errors.js
  99. +143 −140 lib/functions/image.js
  100. +174 −185 lib/lexer.js
  101. +67 −67 lib/nodes/arguments.js
  102. +52 −56 lib/nodes/atblock.js
  103. +88 −92 lib/nodes/atrule.js
  104. +59 −62 lib/nodes/binop.js
  105. +99 −102 lib/nodes/block.js
  106. +84 −88 lib/nodes/boolean.js
  107. +58 −62 lib/nodes/call.js
  108. +39 −42 lib/nodes/charset.js
  109. +43 −46 lib/nodes/comment.js
  110. +52 −55 lib/nodes/each.js
  111. +187 −191 lib/nodes/expression.js
  112. +45 −48 lib/nodes/extend.js
  113. +58 −62 lib/nodes/feature.js
  114. +101 −104 lib/nodes/function.js
  115. +82 −86 lib/nodes/group.js
  116. +193 −195 lib/nodes/hsla.js
  117. +126 −130 lib/nodes/ident.js
  118. +53 −57 lib/nodes/if.js
  119. +45 −48 lib/nodes/import.js
  120. +56 −59 lib/nodes/keyframes.js
  121. +86 −89 lib/nodes/literal.js
  122. +50 −54 lib/nodes/media.js
  123. +56 −60 lib/nodes/member.js
  124. +41 −45 lib/nodes/namespace.js
  125. +52 −54 lib/nodes/node.js
  126. +49 −52 lib/nodes/null.js
  127. +200 −200 lib/nodes/object.js
  128. +66 −71 lib/nodes/params.js
  129. +68 −72 lib/nodes/property.js
  130. +83 −86 lib/nodes/query-list.js
  131. +142 −146 lib/nodes/query.js
  132. +35 −38 lib/nodes/return.js
  133. +291 −294 lib/nodes/rgba.js
  134. +73 −75 lib/nodes/root.js
  135. +66 −69 lib/nodes/selector.js
  136. +117 −120 lib/nodes/string.js
  137. +50 −54 lib/nodes/supports.js
  138. +47 −51 lib/nodes/ternary.js
  139. +43 −45 lib/nodes/unaryop.js
  140. +171 −175 lib/nodes/unit.js
  141. +225 −235 lib/parser.js
  142. +208 −213 lib/renderer.js
  143. +220 −218 lib/selector-parser.js
  144. +44 −42 lib/stack/frame.js
  145. +118 −121 lib/stack/index.js
  146. +47 −54 lib/stack/scope.js
  147. +41 −39 lib/token.js
  148. +9 −1 lib/units.js
  149. +512 −513 lib/visitor/compiler.js
  150. +124 −129 lib/visitor/deps-resolver.js
  151. +1,299 −1,302 lib/visitor/evaluator.js
  152. +21 −20 lib/visitor/index.js
  153. +368 −372 lib/visitor/normalizer.js
  154. +162 −168 lib/visitor/sourcemapper.js
  155. +2 −2 package.json
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# These are supported funding model platforms

github: null
github: [stylus]
patreon: null # Replace with a single Patreon username
open_collective: stylus
ko_fi: null # Replace with a single Ko-fi username
4 changes: 0 additions & 4 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -22,10 +22,6 @@ merge of your pull request!

**Why**:

<!-- How were these changes implemented? -->

**How**:

<!-- Have you done all of these things? -->

**Checklist**:
26 changes: 23 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ on:

jobs:
node_tests:
name: 'Test stylus on ${{matrix.os}} with node16'
name: 'Test stylus on ${{matrix.os}} with node18'
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
@@ -22,7 +22,7 @@ jobs:
- uses: actions/setup-node@v3
with:
# The Node.js version to configure
node-version: '16'
node-version: '18'
- name: Install npm dependencies
run: npm install
- name: Print node & npm version
@@ -36,7 +36,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
node: [10, 12, 14, 18]
node: [10, 12, 14, 16, 20]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
@@ -96,3 +96,23 @@ jobs:
run: npm install
- name: Run nyc
run: npx nyc@latest npm run test

deno_tests:
name: 'Test stylus on ${{matrix.os}} with latest stable deno'
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
# Pull repo to test machine
- uses: actions/checkout@v3
# Configures the deno version used on GitHub-hosted runners
- uses: denoland/setup-deno@v1
with:
# Run with latest stable Deno
deno-version: v1.x
- name: Print deno version
# Output useful info for debugging.
run: deno --version
- name: Run Test
run: deno run -A deno/test.ts
4 changes: 4 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
0.60.0 / 2023-08-30
===================
* feat: support [deno](https://deno.com) [#2813](https://github.com/stylus/stylus/pull/2813)

0.59.0 / 2022-08-13
===================
* deps: switching from css to @adobe/css-tools [#2709](https://github.com/stylus/stylus/pull/2709)
4 changes: 0 additions & 4 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -59,10 +59,6 @@ stylus -w style.styl -o style.css
```
You can also [try all stylus features on stylus-lang.com](http://stylus-lang.com/try.html), build something with stylus on [codepen](http://codepen.io) or [RunKit](https://npm.runkit.com/stylus)

### 📖 New Docs (alpha)

Try our new [official documentation website](http://stylus-docs.netlify.app/) and give us feedback via [github issues](https://github.com/stylus/stylus/issues), thanks.

### Community modules

- https://github.com/stylus/stylus/wiki
14 changes: 7 additions & 7 deletions bin/stylus
Original file line number Diff line number Diff line change
@@ -398,25 +398,25 @@ function help(name) {
switch (browser) {
case 'safari':
case 'webkit':
url = 'https://developer.apple.com/library/safari/search/?q=' + name;
url = 'https://developer.apple.com/search/?q=' + name;
break;
case 'opera':
url = 'http://dev.opera.com/search/?term=' + name;
url = 'https://dev.opera.com/search/?q=' + name;
break;
case 'w3c':
url = 'http://www.google.com/search?q=site%3Awww.w3.org%2FTR+' + name;
url = 'https://www.google.com/search?q=site%3Awww.w3.org%2FTR+' + name;
break;
case 'ms':
url = 'http://social.msdn.microsoft.com/search/en-US/ie?query=' + name + '&refinement=59%2c61';
url = 'https://learn.microsoft.com/en-us/search/?terms=' + name;
break;
case 'caniuse':
url = 'http://caniuse.com/#search=' + name;
url = 'https://caniuse.com/?search=' + name;
break;
case 'quirksmode':
url = 'http://www.google.com/search?q=site%3Awww.quirksmode.org+' + name;
url = 'https://www.google.com/search?q=site%3Awww.quirksmode.org+' + name;
break;
default:
url = 'https://developer.mozilla.org/en/CSS/' + name;
url = 'https://developer.mozilla.org/en-US/docs/Web/CSS/' + name;
}

switch (process.platform) {
33 changes: 33 additions & 0 deletions deno/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Mocha from "mocha";

import fs from "node:fs";
import path from "node:path";
import process from "node:process";

globalThis.process = process;

const mocha = new Mocha({
bail: true,
checkLeaks: true,
require: ["chai"],
reporter: "dot",
});

const testDirs = ["test/", "test/middleware/"];

testDirs.forEach((testDir) => {
fs
.readdirSync(testDir)
.filter(function (file) {
if (testDir === "test/" && file === "deno.js") return false;

return file.slice(-3) === ".js";
})
.forEach(function (file) {
mocha.addFile(path.join(testDir, file));
});
});

mocha.run(function (failures) {
process.exitCode = failures ? 1 : 0;
});
7 changes: 7 additions & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
.vitepress/dist
.idea
*.log
node_modules
logs
npm-debug.log*
13 changes: 13 additions & 0 deletions docs/.vitepress/components.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/vue-next/pull/3399
import '@vue/runtime-core'

declare module '@vue/runtime-core' {
export interface GlobalComponents {
HomePage: typeof import('./components/HomePage.vue')['default']
Runkit: typeof import('./components/Runkit.vue')['default']
}
}

export {}
15 changes: 15 additions & 0 deletions docs/.vitepress/components/HomePage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<template>
<div class="content">
<div class="content-container">
<main class="main">
<div class="vp-doc" flex flex-col items-center mt-10>
<p class="text-center opacity-75">
<a href="https://www.netlify.com" rel="noopener noreferrer">
<img src="https://www.netlify.com/v3/img/components/netlify-color-bg.svg" alt="Deploys by Netlify" width="114" height="151">
</a>
</p>
</div>
</main>
</div>
</div>
</template>
34 changes: 34 additions & 0 deletions docs/.vitepress/components/Runkit.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<template>
<div :id="RUNKIT_ID" class="hidden-runkit" >{{CODE}}</div>
</template>

<script setup>
import { onMounted, ref } from 'vue';
const showLoading = ref(true);
const RUNKIT_ID = 'runkit-id';
const CODE = `
const stylus = require("stylus");
const str = \`
// your stylus code here
body
color white
\`
stylus.render(str, { filename: 'playground.css' }, function(err, css){
if (err) throw err;
console.log("stylus compile result: ", css);
});
`
onMounted(() => {
let runkitScript = document.createElement('script');
runkitScript.setAttribute('src', 'https://embed.runkit.com');
runkitScript.setAttribute('data-element-id', RUNKIT_ID);
document.head.appendChild(runkitScript);
});
</script>

<style scoped>
.hidden-runkit {
color: transparent;
}
</style>
273 changes: 273 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
import { defineConfig } from 'vitepress'
import { version } from '../../package.json'
import {
contributing,
font,
github,
ogImage,
ogUrl,
releases,
twitter,
stylusDescription,
stylusName,
} from './meta'

export default defineConfig({
lang: 'en-US',
title: stylusName,
description: stylusDescription,
head: [
['meta', { name: 'theme-color', content: '#ffffff' }],
['link', { rel: 'icon', href: '/logo.svg', type: 'image/svg+xml' }],
['link', { rel: 'alternate icon', href: '/favicon.ico', type: 'image/png', sizes: '16x16' }],
['meta', { name: 'author', content: `${stylusName} contributors` }],
['meta', { name: 'keywords', content: 'css, preprocessor, stylus, styl, stylesheet, css3' }],
['meta', { property: 'og:title', content: stylusName }],
['meta', { property: 'og:description', content: stylusDescription }],
['meta', { property: 'og:url', content: ogUrl }],
['meta', { property: 'og:image', content: ogImage }],
['meta', { name: 'twitter:title', content: stylusName }],
['meta', { name: 'twitter:description', content: stylusDescription }],
['meta', { name: 'twitter:image', content: ogImage }],
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
['link', { href: font, rel: 'stylesheet' }],
['link', { rel: 'mask-icon', href: '/logo.svg', color: '#ffffff' }],
['link', { rel: 'apple-touch-icon', href: '/stylus.png', sizes: '180x180' }],
[
'script',
{ async: 'true', src: 'https://www.googletagmanager.com/gtag/js?id=G-ZWB0JH7RJV' }
],
[
'script',
{},
"window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', 'G-ZWB0JH7RJV');"
]
],
lastUpdated: true,
markdown: {
theme: {
light: 'vitesse-light',
dark: 'vitesse-dark',
},
},
themeConfig: {
logo: '/logo.svg',

editLink: {
repo: 'stylus/stylus',
branch: 'dev',
dir: 'docs',
text: 'Suggest changes to this page',
},

algolia: {
appId: 'O7LII3IXQM',
apiKey: '141079ddcec4eb7078fa8873bea53a03',
indexName: 'stylus-lang'
},

localeLinks: {
text: 'English',
items: [
{ text: '中文', link: 'https://www.stylus-lang.cn' },
{ text: '中文(张鑫旭)', link: 'https://www.zhangxinxu.com/jq/stylus' },
],
},

socialLinks: [
{ icon: 'twitter', link: twitter },
{ icon: 'github', link: github },
],

footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2010-PRESENT tj, iChenLei and stylus contributors',
},

nav: [
{ text: 'Playground', link: '/try' },
{ text: 'Features', link: '/docs/' },
{ text: 'API', link: '/docs/js' },
{ text: 'CLI', link: '/docs/executable' },
{
text: `v${version}`,
items: [
{
text: 'Release Notes ',
link: releases,
},
{
text: 'Contributing ',
link: contributing,
},
],
},
],

sidebar: {
'/': [
{
text: 'Features',
items: [
{
text: 'Selectors',
link: '/docs/selectors',
},
{
text: 'Variables',
link: '/docs/variables',
},
{
text: 'Interpolation',
link: '/docs/interpolation',
},
{
text: 'Operators',
link: '/docs/operators',
},
{
text: 'Mixins',
link: '/docs/mixins',
},
{
text: 'Functions',
link: '/docs/functions',
},
{
text: 'Keyword Arguments',
link: '/docs/kwargs',
},
{
text: 'Built-in functions',
link: '/docs/bifs',
},
{
text: 'Rest params',
link: '/docs/vargs',
},
{
text: 'Comments',
link: '/docs/comments',
},
{
text: 'Conditionals',
link: '/docs/conditionals',
},
{
text: 'Hashes',
link: '/docs/hashes',
},
{
text: 'Iteration',
link: '/docs/iteration',
},
{
text: 'url()',
link: 'docs/functions.url'
},
{
text: 'css literal',
link: 'docs/literal'
},
{
text: 'css style syntax',
link: 'docs/css-style'
},
{
text: 'char escape',
link: 'docs/escape'
},
{
text: 'executable',
link: 'docs/executable'
},
{
text: 'connect middleware',
link: 'docs/middleware'
},
{
text: 'introspection api',
link: 'docs/introspection'
},
{
text: 'javascript api',
link: 'docs/js'
},
{
text: 'css3 extensions with nib',
link: 'https://stylus.github.io/nib'
}
],
},
{
text: 'At Rules',
items: [
{
text: '@import and @require',
link: '/docs/import',
},
{
text: '@media',
link: '/docs/media',
},
{
text: '@font-face',
link: 'docs/font-face'
},
{
text: '@keyframes',
link: 'docs/keyframes'
},
{
text: '@extend',
link: 'docs/extend'
},
{
text: '@block',
link: 'docs/block'
},
{
text: 'other @-rules',
link: 'docs/atrules'
}
],
},
{
text: 'Debug',
items: [
{
text: 'error-reporting',
link: 'docs/error-reporting'
},
{
text: 'sourcemaps',
link: 'docs/sourcemaps'
},
],
},
{
text: 'CLI',
items: [
{
text: 'cli reference',
link: '/docs/executable',
},
],
},
{
text: 'IDE',
items: [
{
text: 'gedit',
link: '/docs/gedit',
},
{
text: 'textmate',
link: '/docs/textmate',
},
],
},
],
},
},
})
29 changes: 29 additions & 0 deletions docs/.vitepress/meta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// noinspection ES6PreferShortImport: IntelliJ IDE hint to avoid warning to use `~/contributors`, will fail on build if changed

/* Texts */
export const stylusName = 'Stylus'
export const stylusShortName = 'Stylus'
export const stylusDescription = 'Expressive, robust, feature-rich CSS language built for nodejs'

/* CDN fonts and styles */
export const googleapis = 'https://fonts.googleapis.com'
export const gstatic = 'https://fonts.gstatic.com'
export const font = `${googleapis}/css2?family=Readex+Pro:wght@200;400;600&display=swap`

/* vitepress head */
export const ogUrl = 'https://www.stylus-lang.com/'
export const ogImage = `${ogUrl}og.png`

/* GitHub and social links */
export const github = 'https://github.com/stylus/stylus'
export const releases = 'https://github.com/stylus/stylus/releases'
export const contributing = 'https://github.com/stylus/stylus/blob/dev/Contributing.md'
export const twitter = 'https://www.twitter.com/s_chenlei'

/* Avatar/Image/Sponsors servers */
export const preconnectLinks = [googleapis, gstatic]
export const preconnectHomeLinks = [googleapis, gstatic]

/* PWA runtime caching urlPattern regular expressions */
export const pwaFontsRegex = new RegExp(`^${googleapis}/.*`, 'i')
export const pwaFontStylesRegex = new RegExp(`^${gstatic}/.*`, 'i')
93 changes: 93 additions & 0 deletions docs/.vitepress/scripts/assets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { promises as fs } from 'fs'
import fg from 'fast-glob'
import { font, preconnectHomeLinks, preconnectLinks } from '../meta'

const preconnect = `
${preconnectLinks.map(l => `<link rel="dns-prefetch" href="${l}">`).join('\n')}
${preconnectLinks.map(l => `<link rel="preconnect" crossorigin="anonymous" href="${l}">`).join('\n')}
`

const preconnectHome = `
${preconnectHomeLinks.map(l => `<link rel="dns-prefetch" href="${l}">`).join('\n')}
${preconnectHomeLinks.map(l => `<link rel="preconnect" crossorigin="anonymous" href="${l}">`).join('\n')}
`

export const optimizePages = async (pwa: boolean) => {
const names = await fg('./.vitepress/dist/**/*.html', { onlyFiles: true })

await Promise.all(names.map(async (i) => {
let html = await fs.readFile(i, 'utf-8')

let prefetchImg = '\n\t<link rel="prefetch" href="/logo.svg">'

let usePreconnect = preconnect

if (i.endsWith('/dist/index.html')) {
usePreconnect = preconnectHome
prefetchImg = `
${prefetchImg}
\t<link rel="prefetch" href="/netlify.svg">
\t<link rel="prefetch" href="/bg.png">
`
}

// we need the font on development, so the font entry is added in vitepress head
html = html.replace(`<link href="${font.replace('&', '&amp;')}" rel="stylesheet">`, '')

html = html.replace(
/<link rel="stylesheet" href="(.*)">/g,
`
${usePreconnect}
<link rel="preload" as="style" href="$1" />
<link rel="stylesheet" href="$1" />
<link
rel="preload"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
href="${font}"
/>
<noscript>
<link rel="stylesheet" crossorigin="anonymous" href="${font}" />
</noscript>`).trim()

if (pwa) {
html = html.replace(
'</head>',
`
\t<link rel="prefetch" href="/manifest.webmanifest">${prefetchImg}
\t<link rel="manifest" href="/manifest.webmanifest">\n</head>`,
)
}
else {
html = html.replace(
'</head>',
`
${prefetchImg}
</head>`,
)
}

// TODO: dark/light theme, don't remove yet
// html = html.replace(
// '</head>',
// '\t<link rel="manifest" href="/manifest.webmanifest">\n<script>\n'
// + ' (function() {\n'
// + ' const prefersDark = window.matchMedia && window.matchMedia(\'(prefers-color-scheme: dark)\').matches\n'
// + ' const setting = localStorage.getItem(\'color-schema\') || \'auto\'\n'
// + ' if (setting === \'dark\' || (prefersDark && setting !== \'light\'))\n'
// + ' document.documentElement.classList.toggle(\'dark\', true)\n'
// + ' })()\n'
// + ' </script></head>',
// )

html = html.replace(
/aria-hidden="true"/gi,
'tabindex="-1" aria-hidden="true"',
).replace(
/<img class="logo"/gi,
'<img class="logo" width="31" height="31"',
)

await fs.writeFile(i, html, 'utf-8')
}))
}
33 changes: 33 additions & 0 deletions docs/.vitepress/style/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.dark [img-light] {
display: none;
}

html:not(.dark) [img-dark] {
display: none;
}

/* Overrides */

.VPSocialLink {
transform: scale(0.9);
}

.vp-doc th, .vp-doc td {
padding: 6px 10px;
border: 1px solid #8882;
}

/* h3 breaks SEO => replaced with h2 with the same size */
.home-content h2 {
margin-top: 2rem;
font-size: 1.35rem;
border-bottom: none;
margin-bottom: 0;
}

img.resizable-img {
width: unset;
height: unset;
}


89 changes: 89 additions & 0 deletions docs/.vitepress/style/vars.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* Colors
* -------------------------------------------------------------------------- */

:root {
--vp-c-text-dark-3: rgb(33, 53, 71);
--vp-c-accent: #dab40b;
--vp-c-brand: #6da13f;
--vp-c-brand-light: #7ec242;
--vp-c-brand-lighter: #93d31c;
--vp-c-brand-dark: #668d11;
--vp-c-brand-darker: #52730d;
--vp-code-block-bg: #f5f5f5;
--vp-c-text-code: #5d6f5d;
--vp-custom-block-tip-text: rgb(18, 181, 157);
--vp-custom-block-tip-border: rgba(18, 181, 157, 0.5);
--vp-custom-block-tip-bg: rgba(18, 181, 157, 0.1);
}

.dark {
--vp-c-text-code: #c0cec0;
--vp-code-block-bg: rgba(0,0,0,0.2);
--vp-c-text-dark-3: #ffffff;
}

/**
* Component: Code Block
* -------------------------------------------------------------------------- */

.vp-doc div[class*='language-'] {
border: 1px solid #cccccc;
}


/**
* Component: Button
* -------------------------------------------------------------------------- */

:root {
--vp-button-brand-border: var(--vp-c-brand-light);
--vp-button-brand-text: var(--vp-c-text-dark-1);
--vp-button-brand-bg: var(--vp-c-brand);
--vp-button-brand-hover-border: var(--vp-c-brand-light);
--vp-button-brand-hover-text: var(--vp-c-text-dark-1);
--vp-button-brand-hover-bg: var(--vp-c-brand-light);
--vp-button-brand-active-border: var(--vp-c-brand-light);
--vp-button-brand-active-text: var(--vp-c-text-dark-1);
--vp-button-brand-active-bg: var(--vp-button-brand-bg);
}

/**
* Component: Home
* -------------------------------------------------------------------------- */

:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(
120deg,
#86b91a 30%,
#edd532
);
--vp-home-hero-image-background-image: linear-gradient(
-45deg,
#86b91a60 30%,
#edd53260
);
--vp-home-hero-image-filter: blur(30px);
}

@media (min-width: 640px) {
:root {
--vp-home-hero-image-filter: blur(56px);
}
}

@media (min-width: 960px) {
:root {
--vp-home-hero-image-filter: blur(72px);
}
}


/**
* Component: Algolia
* -------------------------------------------------------------------------- */

.DocSearch {
--docsearch-primary-color: var(--vp-c-brand) !important;
}
24 changes: 24 additions & 0 deletions docs/.vitepress/theme/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { h } from 'vue'
import Theme from 'vitepress/theme'
import { inBrowser } from 'vitepress'
import '../style/main.css'
import '../style/vars.css'
import 'uno.css'
import HomePage from '../components/HomePage.vue'
import Runkit from '../components/Runkit.vue'

if (inBrowser)
import('./pwa')

export default {
...Theme,
Layout() {
return h(Theme.Layout, null, {
'home-features-after': () => h(HomePage),
})
},
enhanceApp({ app }) {
app.component('Runkit', Runkit)
}
}

3 changes: 3 additions & 0 deletions docs/.vitepress/theme/pwa.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { registerSW } from 'virtual:pwa-register'

registerSW({ immediate: true })
57 changes: 0 additions & 57 deletions docs/atrules.md

This file was deleted.

1,287 changes: 0 additions & 1,287 deletions docs/bifs.md

This file was deleted.

39 changes: 0 additions & 39 deletions docs/comments.md

This file was deleted.

111 changes: 0 additions & 111 deletions docs/conditionals.md

This file was deleted.

103 changes: 0 additions & 103 deletions docs/css-style.md

This file was deleted.

64 changes: 64 additions & 0 deletions docs/docs/atrules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
layout: default
permalink: docs/atrules.html
---

# Other @-rules

Stylus have a basic support for braceless syntax for most of the CSS @-rules, like `@viewport`, `@page`, `@host`, `@supports` and others:

```stylus
@viewport
color: #00f
@supports (display: flex)
div
display: flex
@page :blank
@top-center
content: none
```

Would compile to

```css
@viewport {
color: #00f;
}
@supports (display: flex) {
div {
display: flex;
}
}
@page :blank {
@top-center {
content: none;
}
}
```
## Unknown at-rules

Stylus supports any yet unknown @-rules, so it is future-friendly, as any new at-rules in CSS could be written in indentation-based syntax of Stylus and would be rendered perfectly:

```stylus
@foo
@bar
width: 10px
.baz
height: 10px
```

Would be compiled to

```css
@foo {
@bar {
width: 10px;
.baz {
height: 10px;
}
}
}
```
1,481 changes: 1,481 additions & 0 deletions docs/docs/bifs.md

Large diffs are not rendered by default.

34 changes: 21 additions & 13 deletions docs/block.md → docs/docs/block.md
Original file line number Diff line number Diff line change
@@ -9,28 +9,36 @@ You can assign any block of code in Stylus to a variable and then call it, pass

To define a block, either write it down with an increased indent after an assign sign:

foo =
width: 20px
height: 20px
```stylus
foo =
width: 20px
height: 20px
```

or use a curly braces syntax with `@block` keyword:

foo = @block {
width: 20px
height: 20px
}
```stylus
foo = @block {
width: 20px
height: 20px
}
```

if you would like to render this block anywhere, you could call this variable inside an interpolation, so

.icon
{foo}
```stylus
.icon
{foo}
```

would render to

.icon {
width: 20px;
height: 20px;
}
```css
.icon {
width: 20px;
height: 20px;
}
```

BTW, this is the same way you can use the blocks passed to the [block mixins](mixins.html#block-mixins).

42 changes: 42 additions & 0 deletions docs/docs/comments.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
layout: default
permalink: docs/comments.html
---

# Comments

Stylus supports three kinds of comments: single-line, and multi-line comments, and multi-line buffered comments.

## Single-line

Single-line comments look like JavaScript comments, and do not output in the resulting CSS:

```stylus
// I'm a comment!
body
padding 5px // some awesome padding
```

## Multi-line

Multi-line comments look identical to regular CSS comments. However, they only output when the `compress` option is not enabled.

```stylus
/*
* Adds the given numbers together.
*/
add(a, b)
a + b
```

## Multi-line buffered

Multi-line comments which are not suppressed start with `/*!`. This tells Stylus to output the comment regardless of compression.

```stylus
/*!
* Adds the given numbers together.
*/
add(a, b)
a + b
```
File renamed without changes.
124 changes: 124 additions & 0 deletions docs/docs/conditionals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
layout: default
permalink: docs/conditionals.html
---

# Conditionals

Conditionals provide control flow to a language which is otherwise static, providing conditional imports, mixins, functions, and more. The examples below are simply examples, and not recommended :)

## if / else if / else

The `if` conditional works as you would expect, simply accepting an expression, evaluating the following block when `true`. Along with `if` are the typical `else if` and `else` tokens, acting as fallbacks.

The example below would conditionally overload the `padding` property, swapping it for `margin`.

```stylus
overload-padding = true
if overload-padding
padding(y, x)
margin y x
body
padding 5px 10px
```

Another example:

```stylus
box(x, y, margin = false)
padding y x
if margin
margin y x
body
box(5px, 10px, true)
```
Another `box()` helper:

```stylus
box(x, y, margin-only = false)
if margin-only
margin y x
else
padding y x
```

## unless

For users familiar with the Ruby programming language, we have the `unless` conditional. It’s basically the opposite of `if`—essentially `if (!(expr))`.

In the example below, if `disable-padding-override` is `undefined` or `false`, `padding` will be overridden, displaying `margin` instead. But if it’s `true`, `padding` will continue outputting `padding 5px 10px` as expected.

```stylus
disable-padding-override = true
unless disable-padding-override is defined and disable-padding-override
padding(x, y)
margin y x
body
padding 5px 10px
```

## Postfix Conditionals

Stylus supports postfix conditionals. This means that `if` and `unless` act as operators; they evaluate the left-hand operand when the right-hand expression is truthy.


For example let's define `negative()` to perform some basic type checking. Below we use block-style conditionals:

```stylus
negative(n)
unless n is a 'unit'
error('invalid number')
if n < 0
yes
else
no
```

Next, we utilize postfix conditionals to keep our function terse.

```stylus
negative(n)
error('invalid number') unless n is a 'unit'
return yes if n < 0
no
```

Of course, we could take this further. For example, we could write `n < 0 ? yes : no`, or simply stick with booleans: `n < 0`.

Postfix conditionals may be applied to most single-line statements. For example, `@import`, `@charset`, mixins—and of course, properties as shown below:

```stylus
pad(types = margin padding, n = 5px)
padding unit(n, px) if padding in types
margin unit(n, px) if margin in types
body
pad()
body
pad(margin)
body
apply-mixins = true
pad(padding, 10) if apply-mixins
```

yielding:

```css
body {
padding: 5px;
margin: 5px;
}
body {
margin: 5px;
}
body {
padding: 10px;
}
```
111 changes: 111 additions & 0 deletions docs/docs/css-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
layout: default
permalink: docs/css-style.html
---

# CSS Style Syntax

Stylus transparently supports a regular CSS-style syntax. This means you don't need an alternative parser, or specify that a certain file uses a specific style.

## Example

Below is a small style using the indented approach:

```stylus
border-radius()
-webkit-border-radius arguments
-moz-border-radius arguments
border-radius arguments
body a
font 12px/1.4 "Lucida Grande", Arial, sans-serif
background black
color #ccc
form input
padding 5px
border 1px solid
border-radius 5px
```

Since braces, colons, and semi-colons are optional, we could write this example just as we would with normal CSS:

```stylus
border-radius() {
-webkit-border-radius: arguments;
-moz-border-radius: arguments;
border-radius: arguments;
}
body a {
font: 12px/1.4 "Lucida Grande", Arial, sans-serif;
background: black;
color: #ccc;
}
form input {
padding: 5px;
border: 1px solid;
border-radius: 5px;
}
```

While Stylus don't support _every_ possible CSS-like syntax, it can understand even such code:

```stylus
border-radius() {
-webkit-border-radius: arguments;
-moz-border-radius: arguments;
border-radius: arguments;
}
body a
{
font: 12px/1.4 "Lucida Grande", Arial, sans-serif;
background: black;
color: #ccc;
}
form input {
padding: 5px;
border: 1px solid;
border-radius: 5px;
}
```

Since we may mix and match the two variants, the following is valid as well:

```stylus
border-radius()
-webkit-border-radius: arguments;
-moz-border-radius: arguments;
border-radius: arguments;
body a {
font: 12px/1.4 "Lucida Grande", Arial, sans-serif;
background: black;
color: #ccc;
}
form input
padding: 5px;
border: 1px solid;
border-radius: 5px;
```
Variables, functions, mixins, and all the other features provided by Stylus still work as expected:

```stylus
main-color = white
main-hover-color = black
body a {
color: main-color;
&:hover { color: main-hover-color; }
}
body a { color: main-color; &:hover { color: main-hover-color; }}
```

There are a few caveats to this rule: since the two styles may be mixed and matched, some indentation rules still apply. So although not _every_ plain-CSS stylesheet will work with zero modification, this feature allows those who prefer CSS syntax to continue doing so while leveraging Stylus' other powerful features.


68 changes: 68 additions & 0 deletions docs/docs/error-reporting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
layout: default
permalink: docs/error-reporting.html
---

# Error Reporting

Stylus has fantastic error reporting built-in for syntax, parse, and evaluation errors—complete with stack traces, line numbers, and filenames.

## Parse Error

Parse error example:

```stylus
body
form input
== padding 5px
```

Yielding:

```bash
ParseError: test.styl:3:16
1| body
2| form input
3| == padding 5px
---------------------^
4|

illegal unary "==", missing left-hand operand
```

## Evaluation Error

This "runtime" or evaluation error is caused by passing a string to `border-radius()`, instead of the expected `Unit` (by using our helper `ensure(n, 'unit')`).

```stylus
ensure(val, type)
unless val is a type
error('expected a ' + type + ', but got ' + typeof(val))
border-radius(n)
ensure(n, 'unit')
-webkit-border-radius n
-moz-border-radius n
border-radius n
body
border-radius '5px'
```

Yielding:

```bash
Error: test.styl:3:62
1| ensure(val, type)
2| unless val is a type
3| error('expected a ' + type + ', but got ' + typeof(val))
-------------------------------------------------------------------^
4|
5| border-radius(n)
6| ensure(n, 'unit')

expected a unit, but got string
at ensure() (test.styl:2:17)
at border-radius() (test.styl:6:16)
at "body" (test.styl:10:18)
```
40 changes: 40 additions & 0 deletions docs/docs/escape.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
layout: default
permalink: docs/escape.html
---

# Char Escaping

Stylus lets you escape characters. This effectively turns them into identifiers, allowing them to be rendered as literals.

For example:

```stylus
body
padding 1 \+ 2
```

Compiles to:

```css
body {
padding: 1 + 2;
}
```

Note that Stylus requires that `/` is parenthesized when used in a property:

```stylus
body
font 14px/1.4
font (14px/1.4)
```

yields:

```css
body {
font: 14px/1.4;
font: 10px;
}
```
309 changes: 309 additions & 0 deletions docs/docs/executable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
---
layout: default
permalink: docs/executable.html
---

# Get styling with Stylus

Installing Stylus is very easy once you have [Node.js](https://nodejs.org/).
So get the binaries for your platform and make sure that they also include npm, Node's package manager.

Now, type in your terminal:

```bash
# npm
$ npm install stylus -g

# pnpm
$ pnpm add -g stylus
```

If you want an expressive css language for nodejs with these
features or the features listed below, head over to 
[GitHub](https://github.com/stylus/stylus)
for more information.

## Stylus cli

Stylus ships with the `stylus` executable for converting Stylus to CSS.

```bash
Usage: stylus [options] [command] [< in [> out]]
[file|dir ...]

Commands:

help [<type>:]<prop> Opens help info at MDC for <prop> in
your default browser. Optionally
searches other resources of <type>:
safari opera w3c ms caniuse quirksmode

Options:

-i, --interactive Start interactive REPL
-u, --use <path> Utilize the Stylus plugin at <path>
-U, --inline Utilize image inlining via data URI support
-w, --watch Watch file(s) for changes and re-compile
-o, --out <dir> Output to <dir> when passing files
-C, --css <src> [dest] Convert CSS input to Stylus
-I, --include <path> Add <path> to lookup paths
-c, --compress Compress CSS output
-d, --compare Display input along with output
-f, --firebug Emits debug infos in the generated CSS that
can be used by the FireStylus Firebug plugin
-l, --line-numbers Emits comments in the generated CSS
indicating the corresponding Stylus line
-m, --sourcemap Generates a sourcemap in sourcemaps v3 format
--sourcemap-inline Inlines sourcemap with full source text in base64 format
--sourcemap-root <url> "sourceRoot" property of the generated sourcemap
--sourcemap-base <path> Base <path> from which sourcemap and all sources are relative
-P, --prefix [prefix] Prefix all css classes
-p, --print Print out the compiled CSS
--import <file> Import stylus <file>
--include-css Include regular CSS on @import
-D, --deps Display dependencies of the compiled file
--disable-cache Disable caching
--hoist-atrules Move @import and @charset to the top
-r, --resolve-url Resolve relative urls inside imports
--resolve-url-nocheck Like --resolve-url but without file existence check
-V, --version Display the version of Stylus
-h, --help Display help information
```
## STDIO Compilation Example
`stylus` reads from _stdin_ and outputs to _stdout_, so for example:
```bash
$ stylus --compress < some.styl > some.css
```
Try Stylus some in the terminal! Type below and press `CTRL-D` for `__EOF__`:
```bash
$ stylus
body
color red
font 14px Arial, sans-serif
```
## Compiling Files Example
`stylus` also accepts files and directories. For example, a directory named `css` will compile and output `.css` files in the same directory.
```bash
$ stylus css
```
The following will output to `./public/stylesheets`:
```bash
$ stylus css --out public/stylesheets
```
Or a few files:
```bash
$ stylus one.styl two.styl
```
For development purposes, you can use the `linenos` option to emit comments indicating
the Stylus filename and line number in the generated CSS:
```bash
$ stylus --line-numbers <path>
```
Or the `firebug` option if you want to use
the [FireStylus extension for Firebug](/docs/firebug.md):
```bash
$ stylus --firebug <path>
```
## Prefixing classes
`stylus` executable provides you a way to prefix all the generated styles using `--prefix` option with given `[prefix]`,
```bash
$ stylus --prefix foo-
```
used with this code:
```stylus
.bar
width: 10px
```
would yield
```css
.foo-bar {
width: 10px;
}
```
All the classes would be prefixed: interpolated, extended etc.
## Converting CSS
If you wish to convert CSS to the terse Stylus syntax, use the `--css` flag.
Via stdio:
```bash
$ stylus --css < test.css > test.styl
```
Output a `.styl` file of the same basename:
```stylus
$ stylus --css test.css
```
Output to a specific destination:
```stylus
$ stylus --css test.css /tmp/out.styl
```
## CSS Property Help
On OS X, `stylus help <prop>` will open your default browser and display help documentation for the given `<prop>`.
```stylus
$ stylus help box-shadow
```
## Interactive Shell
The Stylus REPL (Read-Eval-Print-Loop) or "interactive shell" allows you to
play around with Stylus expressions directly from your terminal.
**Note that this works only for expressions**—not selectors, etc. To use simple add the `-i`, or `--interactive` flag:
```bash
$ stylus -i
> color = white
=> #fff
> color - rgb(200,50,0)
=> #37cdff
> color
=> #fff
> color -= rgb(200,50,0)
=> #37cdff
> color
=> #37cdff
> rgba(color, 0.5)
=> rgba(55,205,255,0.5)
```
## Resolving relative urls inside imports
By default Stylus don't resolve the urls in imported `.styl` files, so if you'd happen to have a `foo.styl` with `@import "bar/bar.styl"` which would have `url("baz.png")`, it would be `url("baz.png")` too in a resulting CSS.
But you can alter this behavior by using `--resolve-url` (or just `-r`) option to get `url("bar/baz.png")` in your resulting CSS.
## List dependencies
You can use `--deps` (or just `-D`) flag to get a list of dependencies of the compiled file.
For example, suppose we have `test.styl`:
```stylus
@import 'foo'
@import 'bar'
```
And inside `foo.styl`:
```stylus
@import 'baz'
```
Running:
```stylus
$ stylus --deps test.styl
```
Will give us list of the imports paths:
```bash
foo.styl
baz.styl
bar.styl
```
**Note that currently this does not works for dynamically generated paths**.
## Utilizing Plugins
For this example we'll use the [nib](https://github.com/visionmedia/nib) Stylus plugin to illustrate its CLI usage.
Suppose we have the following Stylus, which imports nib to use its `linear-gradient()` function.
```stylus
@import 'nib'
body
background: linear-gradient(20px top, white, black)
```
Our first attempt to render using `stylus(1)` via stdio might look like this:
```bash
$ stylus < test.styl
```
Which would yield the following error (because Stylus doesn't know where to find nib).
```bash
Error: stdin:3
1|
2|
> 3| @import 'nib'
4|
5| body
6| background: linear-gradient(20px top, white, black)
```
For plugins that simply supply Stylus APIs, we could add the path to the Stylus lookup paths. We do so by using the `--include` or `-I` flag:
```bash
$ stylus < test.styl --include ../nib/lib
```
Now yielding the output below. (As you might notice, calls to `gradient-data-uri()` and `create-gradient-image()` output as literals. This is because exposing the library path isn't enough when a plugin provides a JavaScript API. However, if we only wanted to use pure-Stylus nib functions, we'd be fine.)
```css
body {
background: url(gradient-data-uri(create-gradient-image(20px, top)));
background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(1, #000));
background: -webkit-linear-gradient(top, #fff 0%, #000 100%);
background: -moz-linear-gradient(top, #fff 0%, #000 100%);
background: linear-gradient(top, #fff 0%, #000 100%);
}
```
So, what we need to do is use the `--use`, or `-u` flag. It expects a path to a node module (with or without the `.js` extension). This `require()`s the module, expecting a function to be exported as `module.exports`, which then calls `style.use(fn())` to expose the plugin (defining its js functions, etc.).
```bash
$ stylus < test.styl --use ../nib/lib/nib
```
Yielding the expected result:
```css
body {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAUCAYAAABMDlehAAAABmJLR0QA/wD/AP+gvaeTAAAAI0lEQVQImWP4+fPnf6bPnz8zMH358oUBwkIjKJBgYGNj+w8Aphk4blt0EcMAAAAASUVORK5CYII=");
background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(1, #000));
background: -webkit-linear-gradient(top, #fff 0%, #000 100%);
background: -moz-linear-gradient(top, #fff 0%, #000 100%);
background: linear-gradient(top, #fff 0%, #000 100%);
}
```
If you need to pass arguments to the plugin, use the `--with` option. `--with` evaluates any valid javascript expression and passes its value to the plugin. For example:
```stylus
$ stylus < test.styl --use ../node_modules/autoprefixer-stylus --with "{ browsers: ['ie 7', 'ie 8'] }"
```
224 changes: 224 additions & 0 deletions docs/docs/extend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
---
layout: default
permalink: docs/extend.html
---

# @extend

The Stylus __@extend__ directive is inspired by (and essentially the same as) the [SASS Implementation](https://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#extend), with few subtle differences. This feature significantly simplifies maintenance of semantic rulesets that inherit from other semantic rulesets.


## “Extending” with mixins

Although you can use mixins to achieve a similar effect, this can lead to duplicate CSS. A typical pattern is to define several classes as shown below, then combine them on the element such as "warning message".

While this technique works just fine, it's difficult to maintain.

```css
.message,
.warning {
padding: 10px;
border: 1px solid #eee;
}

.warning {
color: #E2E21E;
}
```

## Using __`@extend`__

To produce this same output with __`@extend`__, simply pass it the desired selector (note that `@extend` and `@extends` are equal, one is just an alias of another). Stylus will then append the `.warning` selector to the existing `.message` ruleset. The `.warning` class then inherits properties from `.message`.

```stylus
.message {
padding: 10px;
border: 1px solid #eee;
}
.warning {
@extend .message;
color: #E2E21E;
}
```

Here's a more complex example, demonstrating how __`@extend`__ cascades:

```stylus
red = #E33E1E
yellow = #E2E21E
.message
padding: 10px
font: 14px Helvetica
border: 1px solid #eee
.warning
@extends .message
border-color: yellow
background: yellow + 70%
.error
@extends .message
border-color: red
background: red + 70%
.fatal
@extends .error
font-weight: bold
color: red
```

Yielding the following CSS:

```css
.message,
.warning,
.error,
.fatal {
padding: 10px;
font: 14px Helvetica;
border: 1px solid #eee;
}
.warning {
border-color: #e2e21e;
background: #f6f6bc;
}
.error,
.fatal {
border-color: #e33e1e;
background: #f7c5bc;
}
.fatal {
font-weight: bold;
color: #e33e1e;
}
```

Where Stylus currently differs from SASS is, SASS won't allow __`@extend`__ nested selectors:

```stylus
form
button
padding: 10px
a.button
@extend form button
Syntax error: Can't extend form button: can't extend nested selectors
on line 6 of standard input
Use --trace for backtrace.
```

With Stylus, as long as the selectors match, it works!

```stylus
form
input[type=text]
padding: 5px
border: 1px solid #eee
color: #ddd
textarea
@extends form input[type=text]
padding: 10px
```

Yielding:

```css
form input[type=text],
textarea {
padding: 5px;
border: 1px solid #eee;
color: #ddd;
}
textarea {
padding: 10px;
}
```

## Extending multiple selectors

Stylus allows you to extend multiple selectors at once, just write them with the comma:

```stylus
.a
color: red
.b
width: 100px
.c
@extend .a, .b
height: 200px
```

Yielding:

```css
.a,
.c {
color: #f00;
}
.b,
.c {
width: 100px;
}
.c {
height: 200px;
}
```
## Extending placeholder selectors

Stylus has a feature similar to the one in [Sass](https://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#placeholders) — placeholder selectors.

Those selectors should start with a `$` symbol (for example, `$foo`), and are not yielded in the resulting CSS. But you can still extend them:

```stylus
$foo
color: #FFF
$foo2
color: red
.bar
background: #000
@extends $foo
.baz
@extends $foo
```

Yielding:

```css
.bar,
.baz {
color: #fff;
}
.bar {
background: #000;
}
```

Note that if the selector is not extended, it won't be in the resulting CSS, so it's a powerful way to create a library of extendable code. While you can insert code through mixins, they would insert the same code every time you use them, while extending placeholders would give you compact output.

## Optional extending

Sometimes it might be usefull to be able to extend something that might or might not exist depending on the context. You can suffix any selector with `!optional` to achieve this:

```stylus
$specialDesign
color: #FFF
.btn
@extend .design !optional, $specialDesign !optional
```

Yielding:

```css
.btn {
color: #fff;
}
```
67 changes: 67 additions & 0 deletions docs/docs/firebug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
layout: default
permalink: docs/firebug.html
---

# FireStylus extension for Firebug

[FireStylus](https://github.com/parallel/firestylus) is a Firebug extension
that makes Firebug display the Stylus filename and line numbers of
the Stylus-generated CSS styles rather than those of the generated CSS.

![Screenshot](https://raw.github.com/parallel/firestylus/master/src/chrome/skin/screenshot.png)

## Usage

First, you need to install [Firebug](https://addons.mozilla.org/firefox/downloads/latest/1843/addon-1843-latest.xpi?src=addondetail)
and the [FireStylus extension](https://github.com/parallel/firestylus)

Then simply enable the Stylus's `firebug` option when generating CSS.

Command line usage:

```bash
$ stylus -f <path>
$ stylus --firebug <path>
```
Javascript usage:

```css
var stylus = require('stylus');

stylus(str)
.set('firebug', true)
.render(function(err, css){
// logic
});
```

Connect / Express:

```css
var stylus = require('stylus');

var server = connect.createServer(
stylus.middleware({
src: __dirname
, dest: __dirname + '/public'
, firebug: true
})
, connect.static(__dirname + '/public')
);
```

## Compatibility

FireStylus should work with Firefox versions 3.0 and up, and with Firebug versions 1.4 and up.

- Firefox 3+ (also works with version 5)
- Firebug 1.4+

## Limitations

FireStylus and FireSass are incompatible. You cannot enable them
simultaneously.

FireStylus (like FireSass) only works in the HTML pane of Firebug. The others
(such as the CSS pane) won't work due to Firebug limitations.
31 changes: 31 additions & 0 deletions docs/docs/font-face.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
layout: default
permalink: docs/font-face.html
---

# @font-face

The `@font-face` at-rule expects as you would expect. Simply add a block of properties after it, like so:

```stylus
@font-face
font-family Geo
font-style normal
src url(fonts/geo_sans_light/GensansLight.ttf)
.ingeo
font-family Geo
```

Yielding:

```css
@font-face {
font-family: Geo;
font-style: normal;
src: url("fonts/geo_sans_light/GensansLight.ttf");
}
.ingeo {
font-family: Geo;
}
```
283 changes: 283 additions & 0 deletions docs/docs/functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
---
layout: default
permalink: docs/functions.html
---

# Functions

Stylus features powerful in-language function definitions. Function definitions appear identical to mixins; however, functions may return a value.

## Return Values

Let's try a trivial example: creating a function that adds two numbers.

```stylus
add(a, b)
a + b
```

We can then use this function in conditions, in property values, etc.

```stylus
body
padding add(10px, 5)
```

Rendering:

```css
body {
padding: 15px;
}
```

## Argument Defaults

Optional arguments may default to a given expression. With Stylus we may even default arguments to earlier arguments!

For example:

```stylus
add(a, b = a)
a + b
add(10, 5)
// => 15
add(10)
// => 20
```

**Note:** Since argument defaults are assignments, we can also use function calls for defaults:

```stylus
add(a, b = unit(a, px))
a + b
```

## Named Parameters

Functions accept named parameters. This frees you from remembering the order of parameters, or simply improves the readability of your code.

For example:

```stylus
subtract(a, b)
a - b
subtract(b: 10, a: 25)
```

## Function Bodies

We can take our simple `add()` function further. Let's casting all units passed as `px` via the `unit()` built-in. It reassigns each argument, and provides a unit-type string (or identifier), which ignores unit conversion.

```stylus
add(a, b = a)
a = unit(a, px)
b = unit(b, px)
a + b
add(15%, 10deg)
// => 25
```

## Multiple Return Values

Stylus functions can return several values—just as you can assign several values to a variable.

For example, the following is a valid assignment:

```stylus
sizes = 15px 10px
sizes[0]
// => 15px
```

Similarly, we may return several values:

```stylus
sizes()
15px 10px
sizes()[0]
// => 15px
```

One slight exception is when return values are identifiers. For example, the following looks like a property assignment to Stylus (since no operators are present):

```stylus
swap(a, b)
b a
```

To disambiguate, we can either wrap with parentheses, or use the `return` keyword:

```stylus
swap(a, b)
(b a)
swap(a, b)
return b a
```

## Conditionals

Let's say we want to create a function named `stringish()` to determine whether the argument can be transformed to a string. We check if `val` is a string, or an ident (which is string-like). Because undefined identifiers yield themselves as the value, we may compare them to themselves as shown below (where `yes` and `no` are used in place of `true` and `false`):

```stylus
stringish(val)
if val is a 'string' or val is a 'ident'
yes
else
no
```

Usage:

```stylus
stringish('yay') == yes
// => true
stringish(yay) == yes
// => true
stringish(0) == no
// => true
```

__note__: `yes` and `no` are not boolean literals. They are simply undefined identifiers in this case.

Another example:

```stylus
compare(a, b)
if a > b
higher
else if a < b
lower
else
equal
```

Usage:

```stylus
compare(5, 2)
// => higher
compare(1, 5)
// => lower
compare(10, 10)
// => equal
```

## Aliasing

To alias a function, simply assign a function's name to a new identifier. For example, our `add()` function could be aliased as `plus()`, like so:
```stylus
plus = add
plus(1, 2)
// => 3
```
## Variable Functions

In the same way that we can "alias" a function, we can pass a function as well. Here, our `invoke()` function accepts a function, so we can pass it `add()` or `sub()`.

```stylus
add(a, b)
a + b
sub(a, b)
a - b
invoke(a, b, fn)
fn(a, b)
body
padding invoke(5, 10, add)
padding invoke(5, 10, sub)
```

Yielding:

```css
body {
padding: 15;
padding: -5;
}
```

## Anonymous functions

You can use anonymous functions where needed using `@(){}` syntax. Here is how you could use it to create a custom `sort()` function:

```stylus
sort(list, fn = null)
// default sort function
if fn == null
fn = @(a, b) {
a > b
}
// bubble sort
for $i in 1..length(list) - 1
for $j in 0..$i - 1
if fn(list[$j], list[$i])
$temp = list[$i]
list[$i] = list[$j]
list[$j] = $temp
return list
sort('e' 'c' 'f' 'a' 'b' 'd')
// => 'a' 'b' 'c' 'd' 'e' 'f'
sort(5 3 6 1 2 4, @(a, b){
a < b
})
// => 6 5 4 3 2 1
```

## arguments

The `arguments` local is available to all function bodies, and contains all the arguments passed.

For example:

```stylus
sum()
n = 0
for num in arguments
n = n + num
sum(1,2,3,4,5)
// => 15
```

## Hash Example

Below we define the `get(hash, key)` function, which returns the
value of `key` (or `null`). We iterate each `pair` in `hash`, returning the pair's second node when the first (the `key`) matches.

```stylus
get(hash, key)
return pair[1] if pair[0] == key for pair in hash
```

As demonstrated below, in-language functions—paired with robust Stylus expressions—can provide great flexibility:

```stylus
hash = (one 1) (two 2) (three 3)
get(hash, two)
// => 2
get(hash, three)
// => 3
get(hash, something)
// => null
```
61 changes: 35 additions & 26 deletions docs/functions.url.md → docs/docs/functions.url.md
100755 → 100644
Original file line number Diff line number Diff line change
@@ -7,59 +7,68 @@ permalink: docs/functions.url.html

## Data URI Image Inlining

Stylus is bundled with an optional function named `url()`, which replaces the literal `url()` calls (and conditionally inlines them using base64 [Data URIs](http://en.wikipedia.org/wiki/Data_URI_scheme)).
Stylus is bundled with an optional function named `url()`, which replaces the literal `url()` calls (and conditionally inlines them using base64 [Data URIs](https://en.wikipedia.org/wiki/Data_URI_scheme)).

## Example

The function itself is available via `require('stylus').url`. It accepts an `options` object, returning a function that Stylus calls internally when it sees `url()`.

The `.define(name, callback)` method assigned a JavaScript function that can be called from Stylus source. In this case, since our images are in `./css/images`, we can ignore the `paths` option (by default image lookups are performed relative to the file being rendered). But if desired, this behavior can be altered:

stylus(str)
.set('filename', __dirname + '/css/test.styl')
.define('url', stylus.url())
.render(function(err, css){
// render it
});
```js
stylus(str)
.set('filename', __dirname + '/css/test.styl')
.define('url', stylus.url())
.render(function(err, css){
// render it
});
```

For example, imagine our images live in `./public/images`. We want to use `url(images/tobi.png)`. We could pass `paths` our public directory, so that it becomes part of the lookup process.

Likewise, if instead we wanted `url(tobi.png)`, we could pass `paths: [__dirname + '/public/images']`.

stylus(str)
.set('filename', __dirname + '/css/test.styl')
.define('url', stylus.url({ paths: [__dirname + '/public'] }))
.render(function(err, css){
// render it
});
```js
stylus(str)
.set('filename', __dirname + '/css/test.styl')
.define('url', stylus.url({ paths: [__dirname + '/public'] }))
.render(function(err, css){
// render it
});
```

### `utf8` encoding for SVGs

Since base64 encoding an image actually increases the original size, you have the option to use `utf8` encoding when inlining SVGs.

There is a bif for this: `embedurl`:

.embed-with-utf8 {
background-image: embedurl("circle.svg", "utf8");
}
```css
.embed-with-utf8 {
background-image: embedurl("circle.svg", "utf8");
}
```

Would result in utf-encoded inline SVG instead of base64 one.

If you'd like to use the JS define so you could use the `paths` alongside the utf encoding, you'll need to define it using another name, not `url()`. This is Due to how `url()` function is parsed in Stylus: it is impossible now to pass the extra param to it, so you couldn't just call `url` with the second param to set the encoding. But if you'd define the `url` with another name:

stylus(str)
.set('filename', __dirname + '/css/test.styl')
.define('inline-url', stylus.url({ paths: [__dirname + '/public'] }))
.render(function(err, css){
// render it
});
```js
stylus(str)
.set('filename', __dirname + '/css/test.styl')
.define('inline-url', stylus.url({ paths: [__dirname + '/public'] }))
.render(function(err, css){
// render it
});
```

You could then use `inline-url` bif just like you can use `embedurl`, but with an added `paths` functionality:

.embed-with-utf8-at-path {
background-image: inline-url("tobi.svg", "utf8");
}

```css
.embed-with-utf8-at-path {
background-image: inline-url("tobi.svg", "utf8");
}
```
## Options

- `limit` bytesize limit defaulting to 30Kb (30000), use `false` to disable the limit
39 changes: 39 additions & 0 deletions docs/docs/gedit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
layout: default
permalink: docs/gedit.html
---

# gedit language-spec

Stylus ships with a temporary version of `styl.lang` for [GtkSourceView](https://live.gnome.org/GtkSourceView), based off [Yanekk](https://github.com/yanekk)'s [work](https://github.com/gmate/gmate/blob/master/lang-specs/scss.lang) on `scss.lang`.

![Stylus Language Specification for GtkSourceView](https://i.imgur.com/uBppL.png))

This is a start and provides a basic [language spec](https://live.gnome.org/Gedit/NewLanguage) for GtkSourceView editors such as [gedit](https://projects.gnome.org/gedit/).

**Installation Steps**

Download `styl.lang` to your local `language-specs` folder:

```bash
mkdir -p ~/.local/share/gtksourceview-2.0/language-specs/ && wget https://raw.github.com/stylus/stylus/master/editors/gedit/styl.lang -O ~/.local/share/gtksourceview-2.0/language-specs/styl.lang
```

For gtksourceview 3.0 (gedit 3.0), user:

```bash
mkdir -p ~/.local/share/gtksourceview-3.0/language-specs/ && wget https://raw.github.com/stylus/stylus/master/editors/gedit/styl.lang -O ~/.local/share/gtksourceview-3.0/language-specs/styl.lang
```

Update the MIME database and enjoy Stylus syntax in gedit!

```bash
cd ~/.local/share
update-mime-database mime
```

This is much more enjoyable than having gedit recognize your `.styl` files as Apache Confs!

---

**Have a sweet tooth?** Add more icing to gedit with gedit-icing: [https://github.com/niftylettuce/gedit-icing](https://github.com/niftylettuce/gedit-icing)
206 changes: 206 additions & 0 deletions docs/docs/hashes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
---
layout: default
permalink: docs/hashes.html
---

# Hashes

In `0.39.0` version Stylus got hash objects.

## Define

You can define a hash using the curly braces and colons to divide the keys and values:

```stylus
foo = {
bar: baz,
baz: raz
}
```

the keys should be either proper idents or strings:

```stylus
foo = {
bar: baz,
'baz': raz,
'0': raz
}
```

When you already have a hash, you can set its values using brackets and strings inside:

```stylus
foo = {}
foo['bar'] = baz
foo['baz'] = raz
```

Note that while you can't use variables or interpolations in curly braces defines, you can use variables inside brackets:

```stylus
foo = {}
bar = 'baz'
foo[bar] = raz
foo.baz
// => raz
```
### Anonymous hash

We can create anonymous hash objects for list, a kind object with out variable name.

```stylus
list = foo {int: 1, str: '1'} {node: a-node, color: #32E}
list[0]
// => foo
type(list[0])
// => 'ident'
type(list[1])
// => 'object'
list[1].int
// => 1
list[2].color
// => #32E
```

To access its values, we can use both brackets syntax (`['str']`) and dot syntax (`.`). Brackets syntax works well for programming, meanwhile dot syntax is more readable and JSON-alike syntax. It works well with iteration and conditional statement as well.

## Getters

For retrieving values from hashes you can use the dot for idents:

```stylus
foo = { bar: "baz" }
foo.bar
// => "baz"
```

Or brackets with strings for anything:

```stylus
foo = { "%": 10 }
baz = "%"
foo[baz]
// => 10
```

You can use any combinations you want:

```stylus
foo = {
bar: {
baz: {
raz: 10px
}
}
}
qux = "raz"
foo["bar"].baz[qux]
// => 10px
```

## Interpolation

Hashes used inside an interpolation would output the content of the hashes as CSS (without almost any Stylus features though):

```stylus
foo = {
width: 10px,
height: 20px,
'&:hover': {
padding: 0
}
}
.bar
{foo}
// => .bar {
// width: 10px;
// height: 20px;
// }
// .bar:hover {
// padding: 0;
// }
```

## Other stuff

You can use other normal Stylus stuff with hashes, like `length()`:

```stylus
foo = { bar: 'a', baz: 'b' }
length(foo)
// => 2
```

You can iterate through hashes with optional key param:

```stylus
foo = { width: 10px, height: 20px }
for key, value in foo
{key}: value
// => width: 10px;
// height: 20px;
```

You can check existence of a key in hash using `in`:

```stylus
foo = { bar: 10px}
bar in foo
// => true
baz in foo
// => false
```

You can get keys or values of the hash using corresponding bifs:

```stylus
foo = { bar: 'a', baz: 'b' }
keys(foo)
// => 'bar' 'baz'
values(foo)
// => 'a' 'b'
```

You can remove a key from the hash using `remove` bif:

```stylus
obj = { foo: 1, bar: 2 }
remove(obj, 'foo')
// => {"bar":"(2)"}
```

And you can use `merge` (aliased as `extend`) to merge hashes:

```stylus
obj = {
foo: 'foo'
bar: 'bar'
}
obj2 = {
baz: 'baz'
}
merge(obj, obj2)
// => {"foo":"('foo')","bar":"('bar')","baz":"('baz')"}
```
159 changes: 91 additions & 68 deletions docs/import.md → docs/docs/import.md
Original file line number Diff line number Diff line change
@@ -9,13 +9,16 @@ Stylus supports both literal __@import__ for CSS, as well as dynamic importing o

## Literal CSS

Any filename with the extension `.css` will become a literal. For example:

@import "reset.css"
Any filename with the extension `.css` will become a literal. For example:

```stylus
@import "reset.css"
```
Render the literal CSS __@import__ shown below:

@import "reset.css"
```stylus
@import "reset.css"
```

## Stylus Import

@@ -29,33 +32,37 @@ Render the literal CSS __@import__ shown below:

For example, a common lib structure might be:

./tablet
|-- index.styl
|-- vendor.styl
|-- buttons.styl
|-- images.styl

In the example below, we set the `paths` options to provide additional paths to Stylus. Within `./test.styl`, we could then `@import "mixins/border-radius"`, or `@import "border-radius"` (since `./mixins` is exposed to Stylus).

/**
* Module dependencies.
*/

var stylus = require('../')
, str = require('fs').readFileSync(__dirname + '/test.styl', 'utf8');

var paths = [
__dirname
, __dirname + '/mixins'
];

stylus(str)
.set('filename', __dirname + '/test.styl')
.set('paths', paths)
.render(function(err, css){
if (err) throw err;
console.log(css);
});
```bash
./tablet
|-- index.styl
|-- vendor.styl
|-- buttons.styl
|-- images.styl
```

In the example below, we set the `paths` options to provide additional paths to Stylus. Within `./test.styl`, we could then `@import "mixins/border-radius"`, or `@import "border-radius"` (since `./mixins` is exposed to Stylus).

```js
/**
* Module dependencies.
*/

var stylus = require('../')
, str = require('fs').readFileSync(__dirname + '/test.styl', 'utf8');

var paths = [
__dirname
, __dirname + '/mixins'
];

stylus(str)
.set('filename', __dirname + '/test.styl')
.set('paths', paths)
.render(function(err, css){
if (err) throw err;
console.log(css);
});
```

## Require

@@ -67,46 +74,58 @@ Stylus supports block-level import. It means that you can use `@import` not only

If you have a `bar.styl` with this code:

.bar
width: 10px;
```stylus
.bar
width: 10px;
```

Then you can import it inside a `foo.styl` like this:

.foo
@import 'bar.styl'
```stylus
.foo
@import 'bar.styl'
@media screen and (min-width: 640px)
@import 'bar.styl'
@media screen and (min-width: 640px)
@import 'bar.styl'
```

And you'll get this compiled CSS as a result:

.foo .bar {
width: 10px;
}
@media screen and (min-width: 640px) {
.bar {
width: 10px;
}
}
```stylus
.foo .bar {
width: 10px;
}
@media screen and (min-width: 640px) {
.bar {
width: 10px;
}
}
```

## File globbing

Stylus supports [globbing](https://github.com/isaacs/node-glob#readme). With it you could import many files using a file mask:

@import 'product/*'
```stylus
@import 'product/*'
```

This would import all the stylus sheets from the `product` directory in such structure:

./product
|-- body.styl
|-- foot.styl
|-- head.styl
```bash
./product
|-- body.styl
|-- foot.styl
|-- head.styl
```

Note that this works with `@require` too, so if you would have also a `./product/index.styl` with this content:

@require 'head'
@require 'body'
@require 'foot'
```stylus
@require 'head'
@require 'body'
@require 'foot'
```

then `@require 'product/*'` would include each individual sheet only once.

@@ -118,24 +137,28 @@ But you can alter this behavior by using `--resolve-url` (or just `-r`) CLI opti

## JavaScript Import API

When using the `.import(path)` method, these imports are deferred until evaluation:
When using the `.import(path)` method, these imports are deferred until evaluation:

var stylus = require('../')
, str = require('fs').readFileSync(__dirname + '/test.styl', 'utf8');
```js
var stylus = require('../')
, str = require('fs').readFileSync(__dirname + '/test.styl', 'utf8');

stylus(str)
.set('filename', __dirname + '/test.styl')
.import('mixins/vendor')
.render(function(err, css){
if (err) throw err;
console.log(css);
});
stylus(str)
.set('filename', __dirname + '/test.styl')
.import('mixins/vendor')
.render(function(err, css){
if (err) throw err;
console.log(css);
});
```

The following statement...

@import 'mixins/vendor'
The following statement...

```stylus
@import 'mixins/vendor'
```
...is equivalent to...

.import('mixins/vendor')

```stylus
.import('mixins/vendor')
```
Loading