diff --git a/WORKSPACE b/WORKSPACE index fec6a59cd5..5782952678 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -72,6 +72,11 @@ local_repository( path = "packages/typescript/src", ) +local_repository( + name = "npm_bazel_stylus", + path = "packages/stylus/src", +) + # # Install rules_nodejs dev dependencies # diff --git a/commitlint.config.js b/commitlint.config.js index 6d642cf6cd..7362e28c63 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -15,6 +15,7 @@ module.exports = { 'karma', 'labs', 'protractor', + 'stylus', 'rollup', 'typescript', ] diff --git a/package.json b/package.json index f1fe1c6bce..30fa26ddfa 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "shelljs": "0.8.3", "sinon": "^7.3.2", "source-map-support": "0.5.9", + "stylus": "~0.54.5", "terser": "3.17.0", "tmp": "0.1.0", "tsickle": "0.33.1", diff --git a/packages/stylus/BUILD.bazel b/packages/stylus/BUILD.bazel new file mode 100644 index 0000000000..4d5d6041d6 --- /dev/null +++ b/packages/stylus/BUILD.bazel @@ -0,0 +1,50 @@ +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@build_bazel_rules_nodejs//:defs.bzl", "npm_package") + +# Copy the license from our parent folder +genrule( + name = "copy_LICENSE", + srcs = ["@build_bazel_rules_nodejs//:LICENSE"], + outs = ["LICENSE"], + cmd = "cp $< $@", +) + +# Ugly genrule depending on local linux environment to build the README out of skylark doc generation. +# Only referenced when we do a release. +# TODO: This ought to be possible with stardoc alone. Need to coordinate with Chris Parsons. +genrule( + name = "generate_README", + srcs = [ + "//packages/stylus/docs:index.md", + "//packages/stylus/docs:install.md", + ], + outs = ["README.md"], + cmd = """cat $(location //packages/stylus/docs:install.md) $(location //packages/stylus/docs:index.md) | sed 's/^##/\\\n##/' > $@""", +) + +npm_package( + name = "npm_package", + srcs = [ + "@npm_bazel_stylus//:package_contents", + ], + vendor_external = [ + "npm_bazel_stylus", + ], + deps = [ + ":copy_LICENSE", + ":generate_README", + ], +) diff --git a/packages/stylus/docs/BUILD.bazel b/packages/stylus/docs/BUILD.bazel new file mode 100644 index 0000000000..6c4324f10c --- /dev/null +++ b/packages/stylus/docs/BUILD.bazel @@ -0,0 +1,37 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@io_bazel_skydoc//stardoc:stardoc.bzl", "stardoc") + +package(default_visibility = ["//visibility:public"]) + +exports_files(["install.md"]) + +stardoc( + name = "docs", + testonly = True, + out = "index.md", + input = "@npm_bazel_stylus//:index.bzl", + deps = [ + "@npm_bazel_stylus//:bzl", + # We need to restate local workspace dependencies here in `//foo:bzl` + # format to work-around a bug in stardoc where .bzl files from + # `@build_bazel_rules_nodejs//foo:bzl` style deps are not found + # by the doc generator: + # ``` + # ``` + "//:bzl", + "//internal/common:bzl", + ], +) diff --git a/packages/stylus/docs/install.md b/packages/stylus/docs/install.md new file mode 100644 index 0000000000..1c02fb33d3 --- /dev/null +++ b/packages/stylus/docs/install.md @@ -0,0 +1,16 @@ +# Stylus rules for Bazel + +**WARNING: this is beta-quality software. Breaking changes are likely. Not recommended for production use without expert support.** + +The Stylus rules run the Stylus CSS preprocessor with Bazel. + +## Installation + +Add the `@bazel/stylus` npm package to your `devDependencies` in `package.json`. + +Your `WORKSPACE` should declare a `yarn_install` or `npm_install` rule named `npm`. +It should then install the rules found in the npm packages using the `install_bazel_dependencies' function. +See https://github.com/bazelbuild/rules_nodejs/#quickstart + +This causes the `@bazel/stylus` package to be installed as a Bazel workspace named `npm_bazel_stylus`. + diff --git a/packages/stylus/src/BUILD.bazel b/packages/stylus/src/BUILD.bazel new file mode 100644 index 0000000000..b8b95b89e4 --- /dev/null +++ b/packages/stylus/src/BUILD.bazel @@ -0,0 +1,36 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +load("@npm_bazel_typescript//:defaults.bzl", "ts_library") + +package(default_visibility = ["//visibility:public"]) + +bzl_library( + name = "bzl", + testonly = True, + srcs = glob(["*.bzl"]), + deps = [ + "@build_bazel_rules_nodejs//:bzl", + "@build_bazel_rules_nodejs//internal/common:bzl", + ], +) + +filegroup( + name = "package_contents", + srcs = [ + "index.bzl", + "package.json", + ], +) diff --git a/packages/stylus/src/WORKSPACE b/packages/stylus/src/WORKSPACE new file mode 100644 index 0000000000..9b6438f1a2 --- /dev/null +++ b/packages/stylus/src/WORKSPACE @@ -0,0 +1,15 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +workspace(name = "npm_bazel_stylus") diff --git a/packages/stylus/src/index.bzl b/packages/stylus/src/index.bzl new file mode 100644 index 0000000000..676b374d4d --- /dev/null +++ b/packages/stylus/src/index.bzl @@ -0,0 +1,37 @@ +""" +Support running the stylus processor as a Bazel rule. +""" + +def _stylus_binary(ctx): + src = ctx.file.src + + # We want foo.styl to produce foo.css + output = ctx.actions.declare_file(src.basename[:-5] + ".css") + ctx.actions.run( + outputs = [output], + inputs = [src], + executable = ctx.executable._compiler, + arguments = [ + "--out", + ctx.bin_dir.path + "/" + ctx.label.package, + src.path, + ], + ) + return [ + DefaultInfo(files = depset([output])), + ] + +stylus_binary = rule( + implementation = _stylus_binary, + attrs = { + "src": attr.label( + mandatory = True, + allow_single_file = True, + ), + "_compiler": attr.label( + default = Label("@npm//stylus/bin:stylus"), + cfg = "host", + executable = True, + ), + }, +) diff --git a/packages/stylus/src/package.json b/packages/stylus/src/package.json new file mode 100644 index 0000000000..afa859f5a4 --- /dev/null +++ b/packages/stylus/src/package.json @@ -0,0 +1,29 @@ +{ + "name": "@bazel/stylus", + "dependencies": { + "stylus": "~0.54.5" + }, + "description": "Run Stylus CSS preprocessor under Bazel", + "license": "Apache-2.0", + "version": "0.0.0-PLACEHOLDER", + "repository": { + "type" : "git", + "url" : "https://github.com/bazelbuild/rules_nodejs.git", + "directory": "packages/stylus" + }, + "bugs": { + "url": "https://github.com/bazelbuild/rules_nodejs/issues" + }, + "keywords": [ + "stylus", + "bazel" + ], + "bazelWorkspaces": { + "npm_bazel_stylus": { + "rootPath": "." + } + }, + "scripts": { + "test": "bazel test //..." + } +} \ No newline at end of file diff --git a/packages/stylus/test/BUILD.bazel b/packages/stylus/test/BUILD.bazel new file mode 100644 index 0000000000..1ef116ee27 --- /dev/null +++ b/packages/stylus/test/BUILD.bazel @@ -0,0 +1,17 @@ +load("@npm_bazel_stylus//:index.bzl", "stylus_binary") + +stylus_binary( + name = "styles", + src = "file.styl", +) + +load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_test") + +nodejs_test( + name = "test", + data = [ + "stylus_binary_spec.js", + ":styles", + ], + entry_point = ":stylus_binary_spec.js", +) diff --git a/packages/stylus/test/file.styl b/packages/stylus/test/file.styl new file mode 100644 index 0000000000..a7379c56e4 --- /dev/null +++ b/packages/stylus/test/file.styl @@ -0,0 +1,6 @@ +body { + font: 14px/1.5 Helvetica, arial, sans-serif; + #logo { + border-radius: 5px; + } +} diff --git a/packages/stylus/test/stylus_binary_spec.js b/packages/stylus/test/stylus_binary_spec.js new file mode 100644 index 0000000000..da3d2ad05c --- /dev/null +++ b/packages/stylus/test/stylus_binary_spec.js @@ -0,0 +1,7 @@ +console.log(process.cwd()); +const cssPath = require.resolve('build_bazel_rules_nodejs/packages/stylus/test/file.css'); +const content = require('fs').readFileSync(cssPath, {encoding: 'utf-8'}); +if (content.indexOf('body #logo') < 0) { + console.error('Expected the css file to be transformed'); + process.exitCode = 1; +} diff --git a/yarn.lock b/yarn.lock index 817cd94d1c..6ed08cf4d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -648,6 +648,11 @@ ajv@^6.1.0, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -1731,6 +1736,11 @@ crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" +css-parse@1.7.x: + version "1.7.0" + resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-1.7.0.tgz#321f6cf73782a6ff751111390fc05e2c657d8c9b" + integrity sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs= + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -1772,6 +1782,13 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +debug@*: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -2481,6 +2498,18 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" +glob@7.0.x: + version "7.0.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" + integrity sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo= + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.0.0: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -3556,7 +3585,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.4: +minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -3625,7 +3654,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: +mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -4757,6 +4786,11 @@ saucelabs@^1.5.0: dependencies: https-proxy-agent "^2.2.1" +sax@0.5.x: + version "0.5.8" + resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1" + integrity sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE= + sax@>=0.6.0, sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -4995,6 +5029,13 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= +source-map@0.1.x: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + integrity sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y= + dependencies: + amdefine ">=0.0.4" + source-map@^0.5.6, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -5236,6 +5277,18 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +stylus@~0.54.5: + version "0.54.5" + resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.5.tgz#42b9560931ca7090ce8515a798ba9e6aa3d6dc79" + integrity sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk= + dependencies: + css-parse "1.7.x" + debug "*" + glob "7.0.x" + mkdirp "0.5.x" + sax "0.5.x" + source-map "0.1.x" + subarg@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2"