mirror of
https://github.com/primer/css.git
synced 2025-01-03 03:34:16 +03:00
commit
f6dccec048
19
CHANGELOG.md
19
CHANGELOG.md
@ -1,3 +1,22 @@
|
||||
# 12.4.0
|
||||
|
||||
### :rocket: Enhancement
|
||||
- More responsive border utilities [#775](https://github.com/primer/css/pull/775)
|
||||
- Add `overflow: visible` utilities [#798](https://github.com/primer/css/pull/798)
|
||||
- Add `yellow` color utilities that will replace `pending` [#737](https://github.com/primer/css/pull/737)
|
||||
|
||||
### :bug: Bug Fix
|
||||
- Fix Ruby Sass compiler warnings by quoting keys in `$hue-maps` declaration [#794](https://github.com/primer/css/pull/794)
|
||||
|
||||
### :house: Internal
|
||||
- Remove `test-all-modules` scripts and old monorepo test scripts [#795](https://github.com/primer/css/pull/795)
|
||||
- Resolve all but one ([#796](https://github.com/primer/css/pull/796)) vulnerability in npm dev dependencies [#797](https://github.com/primer/css/pull/797)
|
||||
|
||||
### Committers
|
||||
- [@broccolini](https://github.com/broccolini)
|
||||
- [@shawnbot](https://github.com/shawnbot)
|
||||
- [@simurai](https://github.com/simurai)
|
||||
|
||||
# 12.3.1
|
||||
|
||||
### 🐛 Bug Fix
|
||||
|
6330
package-lock.json
generated
6330
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@primer/css",
|
||||
"version": "12.3.1",
|
||||
"version": "12.4.0",
|
||||
"description": "Primer is the CSS framework that powers GitHub's front-end design. primer includes 23 packages that are grouped into 3 core meta-packages for easy install. Each package and meta-package is independently versioned and distributed via npm, so it's easy to include all or part of Primer within your own project.",
|
||||
"homepage": "https://primer.style/css",
|
||||
"author": "GitHub, Inc.",
|
||||
@ -39,7 +39,6 @@
|
||||
"start-storybook": "start-storybook -p 8001",
|
||||
"build-storybook": "build-storybook -o .storybuild",
|
||||
"test": "npm-run-all -s test-urls test-migrate",
|
||||
"test-all-modules": "ava --verbose tests/test-*.js",
|
||||
"test-urls": "node docs-test/urls.js",
|
||||
"test-migrate": "script/test-migrate"
|
||||
},
|
||||
@ -50,21 +49,18 @@
|
||||
"@primer/blueprints": "4.0.1",
|
||||
"@primer/components": "12.0.1",
|
||||
"@primer/next-pages": "0.0.3",
|
||||
"@storybook/addon-viewport": "5.0.0",
|
||||
"@storybook/react": "5.0.10",
|
||||
"@storybook/addon-viewport": "5.0.11",
|
||||
"@storybook/react": "5.0.11",
|
||||
"@svgr/webpack": "2.4.1",
|
||||
"@zeit/next-css": "^1.0.1",
|
||||
"@zeit/next-css": "1.0.1",
|
||||
"@zeit/next-sass": "^1.0.1",
|
||||
"action-status": "0.1.1",
|
||||
"autoprefixer": "9.4.7",
|
||||
"ava": "^0.23.0",
|
||||
"broken-link-checker": "^0.7.8",
|
||||
"char-spinner": "^1.0.1",
|
||||
"chroma-js": "^1.4.1",
|
||||
"clipboard-copy-element": "^0.5.0",
|
||||
"code-blocks": "^1.1.0",
|
||||
"colorette": "^1.0.7",
|
||||
"css-loader": "^0.28.4",
|
||||
"css-loader": "1.0.0",
|
||||
"cssstats": "3.3.0",
|
||||
"details-dialog-element": "^1.4.0",
|
||||
"eslint": "4.19.1",
|
||||
@ -83,10 +79,6 @@
|
||||
"klaw": "3.0.0",
|
||||
"loader-utils": "^1.1.0",
|
||||
"mdx-constant": "^0.1.0",
|
||||
"metalsmith": "^2.3.0",
|
||||
"metalsmith-filter": "^1.0.2",
|
||||
"metalsmith-matters": "^1.2.0",
|
||||
"metalsmith-watch": "^1.0.3",
|
||||
"minimist": "1.2.0",
|
||||
"next": "7.0.2",
|
||||
"node-fetch": "2.4.0",
|
||||
|
@ -21,7 +21,7 @@ The default border utility applies a solid, 1px border, with a default gray colo
|
||||
</div>
|
||||
```
|
||||
|
||||
Borders can be applied to a specific edge or to the Y axis.
|
||||
Borders can be applied to a specific edge or to the X and Y axes individually:
|
||||
|
||||
```html
|
||||
<div class="d-flex mb-3">
|
||||
@ -38,6 +38,9 @@ Borders can be applied to a specific edge or to the Y axis.
|
||||
.border-right
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-x">
|
||||
.border-x
|
||||
</div>
|
||||
<div class="border-y">
|
||||
.border-y
|
||||
</div>
|
||||
@ -198,10 +201,18 @@ You can also add rounded corners to each edge (top, right, bottom, left) with th
|
||||
|
||||
## Responsive borders
|
||||
|
||||
Top, right, bottom, and left border utilities are can be used responsively to add or remove borders to an element at different screensizes.
|
||||
You can adjust border widths on all sides or each side individually with responsive border utilities:
|
||||
|
||||
* `border-(sm|md|lg|xl)` adds borders on all sides at and above the breakpoint. The `border-(sm|md|lg|xl)` shorthand is also supported.
|
||||
* `border-(sm|md|lg|xl)-0` removes borders from all sides at and above the breakpoint.
|
||||
* `border-(sm|md|lg|xl)-(top|right|bottom|left)` adds a border on the given side at and above the breakpoint.
|
||||
* `border-(sm|md|lg|xl)-(top|right|bottom|left)-0` the border from the given side at and above the breakpoint.
|
||||
|
||||
```html
|
||||
<div class="border-top border-sm-right border-md-bottom border-lg-top-0">
|
||||
.border-top-0
|
||||
<div class="border-top border-sm-right border-md-bottom border-md-top-0">
|
||||
.border-top
|
||||
<span class="d-none d-sm-inline">.border-sm-right </span>
|
||||
<span class="d-none d-md-inline">.border-md-bottom </span>
|
||||
<span class="d-none d-lg-inline">.border-md-top-0 </span>
|
||||
</div>
|
||||
```
|
||||
|
@ -75,9 +75,16 @@ Background colors are most commonly used for filling large blocks of content or
|
||||
</div>
|
||||
<div class="col-9 float-left">
|
||||
<div class="container-lg clearfix">
|
||||
<div class="h4">.bg-yellow-light</div>
|
||||
<code>{colors.yellow[2]}, $bg-yellow-light</code>
|
||||
<Swatch className="bg-yellow-light" />
|
||||
<div class="col-6 float-left">
|
||||
<div class="h4">.bg-yellow-dark</div>
|
||||
<code>{colors.yellow[7]}, $bg-yellow-dark</code>
|
||||
<Swatch className="bg-yellow-dark border-right-0" />
|
||||
</div>
|
||||
<div class="col-6 float-left">
|
||||
<div class="h4">.bg-yellow-light</div>
|
||||
<code>{colors.yellow[2]}, $bg-yellow-light</code>
|
||||
<Swatch className="bg-yellow-light" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -173,6 +180,10 @@ You can set the color inheritance on an element by using the `text-inherit` clas
|
||||
.text-orange-light on white
|
||||
</div>
|
||||
<span class="float-left text-red tooltipped tooltipped-n" aria-label="Does not meet accessibility standards"><%= octicon("alert") %></span>
|
||||
<div class="text-yellow mb-2">
|
||||
.text-yellow on white
|
||||
</div>
|
||||
<span class="float-left text-red tooltipped tooltipped-n" aria-label="Does not meet accessibility standards"><%= octicon("alert") %></span>
|
||||
<div class="text-green mb-2 ml-4">
|
||||
.text-green on white
|
||||
</div>
|
||||
@ -199,6 +210,9 @@ You can set the color inheritance on an element by using the `text-inherit` clas
|
||||
<div class="bg-green-light mb-2">
|
||||
.text-gray-dark on .bg-green-light
|
||||
</div>
|
||||
<div class="bg-yellow-dark mb-2">
|
||||
.text-gray-dark on .bg-yellow-dark
|
||||
</div>
|
||||
<div class="bg-yellow mb-2">
|
||||
.text-gray-dark on .bg-yellow
|
||||
</div>
|
||||
|
@ -105,16 +105,18 @@ Hide utilities are able to be applied or changed per breakpoint using the follow
|
||||
Adjust the visibility of an element with `.v-hidden` and `.v-visible`.
|
||||
|
||||
## Overflow
|
||||
Adjust element overflow with `.overflow-hidden`, `.overflow-scroll`, and `.overflow-auto`. `.overflow-hidden` can also be used to create a new [block formatting context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context) or clear floats.
|
||||
Adjust element overflow with `.overflow-hidden`, `.overflow-scroll`, and `.overflow-auto`, or use `.overflow-visible` to undo the effects of CSS with overflow issues. `.overflow-hidden` can also be used to create a new [block formatting context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context) or clear floats.
|
||||
|
||||
Overflow utilities can also target x- and y-axes independently via:
|
||||
|
||||
* `.overflow-x-auto`
|
||||
* `.overflow-x-hidden`
|
||||
* `.overflow-x-scroll`
|
||||
* `.overflow-x-visible`
|
||||
* `.overflow-y-auto`
|
||||
* `.overflow-y-hidden`
|
||||
* `.overflow-y-scroll`
|
||||
* `.overflow-y-visible`
|
||||
|
||||
## Floats
|
||||
Use `.float-left` and `.float-right` to set floats, and `.clearfix` to clear.
|
||||
|
@ -1,157 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
const spinner = require('char-spinner')
|
||||
const {gray, green, yellow, red, bold} = require('colorette')
|
||||
const {SiteChecker} = require('broken-link-checker')
|
||||
|
||||
const yargs = require('yargs')
|
||||
.option('excluded-schemes', {type: String, alias: 's', default: ['dash-feed', 'mailto']})
|
||||
.option('filter-level', {type: Number, alias: 'L', default: 3})
|
||||
.option('max-sockets-per-host', {type: Number, alias: 'm', default: 1})
|
||||
.option('verbose', {type: Boolean, alias: 'v', default: false})
|
||||
|
||||
const options = yargs.argv
|
||||
|
||||
const args = options._
|
||||
const VERBOSE = options.verbose
|
||||
|
||||
const pages = []
|
||||
const seen = new Set()
|
||||
const excepted = new Map()
|
||||
|
||||
const OK = ' ✓ '
|
||||
const NOT_OK = ' ✘ '
|
||||
const TAG_LENGTH = 3
|
||||
|
||||
const URL = args[0]
|
||||
if (URL) {
|
||||
log(green('go!'), bold(URL))
|
||||
} else {
|
||||
log('err', 'you must provide a URL')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
let page = {url: URL, links: []}
|
||||
|
||||
const exceptions = {
|
||||
'GitHub private repo': url =>
|
||||
[
|
||||
// this is a list of known GitHub private repos
|
||||
'https://github.com/github/accessibility',
|
||||
'https://github.com/github/design',
|
||||
'https://github.com/github/design-systems',
|
||||
'https://github.com/github/github',
|
||||
'https://github.com/github/sentinel'
|
||||
].some(repo => url.startsWith(repo))
|
||||
}
|
||||
|
||||
const checker = new SiteChecker(options, {
|
||||
page(error, url) {
|
||||
if (error) {
|
||||
log(red('ERR'), `${url} (${error.code})`)
|
||||
} else if (page) {
|
||||
const {url, response, links = []} = page
|
||||
const num = String(links.length).padEnd(TAG_LENGTH)
|
||||
let message = `${bold(num)}${pages.length ? ' unique' : ''} links`
|
||||
if (!VERBOSE) message = `${message} on ${yellow(url)}`
|
||||
log(OK, message)
|
||||
if (links.length) {
|
||||
pages.push(page)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
html(tree, robots, response, url) {
|
||||
if (VERBOSE) log(yellow('get'), url)
|
||||
page = {url, links: []}
|
||||
},
|
||||
|
||||
junk(result) {
|
||||
const url = result.url.resolved || result.url.original
|
||||
if (!url || seen.has(url)) {
|
||||
return
|
||||
} else if (VERBOSE) {
|
||||
log(' '.repeat(TAG_LENGTH), gray(`skip ${shorten(url)}`))
|
||||
} else if (result.excluded && url.indexOf(URL) !== 0) {
|
||||
log(yellow('---'), gray(`excluded: ${url}`))
|
||||
}
|
||||
seen.add(url)
|
||||
},
|
||||
|
||||
link(result) {
|
||||
const url = result.url.resolved || result.url.original
|
||||
if (VERBOSE && !seen.has(url)) log(' + ', gray('link'), shorten(url))
|
||||
|
||||
for (const [reason, test] of Object.entries(exceptions)) {
|
||||
if (test(url)) {
|
||||
log(yellow('---'), gray(`skip ${url}`), yellow(reason))
|
||||
excepted.set(url, reason)
|
||||
seen.add(url)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (!seen.has(url)) page.links.push(result)
|
||||
seen.add(url)
|
||||
},
|
||||
|
||||
end() {
|
||||
const allBroken = []
|
||||
for (const page of pages) {
|
||||
const broken = page.links.filter(link => link.broken)
|
||||
allBroken.push(...broken)
|
||||
|
||||
if (!broken.length && !VERBOSE) {
|
||||
continue
|
||||
} else {
|
||||
const num = broken.length ? red(` ${broken.length}`.padEnd(TAG_LENGTH)) : green(' 0').padEnd(TAG_LENGTH)
|
||||
log(bold(num), `broken links on ${bold(page.url)}`)
|
||||
}
|
||||
|
||||
for (const link of page.links) {
|
||||
if (!link.broken && !VERBOSE) continue
|
||||
const tag = link.broken ? red(NOT_OK) : green(OK)
|
||||
const reason = link.broken ? link.brokenReason.replace(/HTTP_/, '') : ''
|
||||
const url = link.url.resolved || link.url.original
|
||||
log(tag, shorten(url), yellow(reason))
|
||||
link.source = url
|
||||
link.reason = reason
|
||||
}
|
||||
log('')
|
||||
}
|
||||
|
||||
if (excepted.size) {
|
||||
log(yellow(OK), `Excepted ${excepted.size} links:`)
|
||||
const exceptedURLs = Array.from(excepted.keys()).sort()
|
||||
for (const url of exceptedURLs) {
|
||||
log(yellow(OK), `${yellow(excepted.get(url))} ${gray(url)}`)
|
||||
}
|
||||
log('')
|
||||
}
|
||||
|
||||
if (allBroken.length) {
|
||||
log(red(NOT_OK), `${red(allBroken.length)} broken links:`)
|
||||
for (const link of allBroken) {
|
||||
log(red(NOT_OK), red(link.reason), link.url.original, gray('from'), shorten(link.source))
|
||||
}
|
||||
log('')
|
||||
process.exitCode = 1
|
||||
} else {
|
||||
log(green(OK), bold('0'), 'broken links')
|
||||
}
|
||||
|
||||
log('')
|
||||
}
|
||||
})
|
||||
|
||||
spinner()
|
||||
checker.enqueue(URL)
|
||||
checker.resume()
|
||||
|
||||
function log(tag, ...args) {
|
||||
spinner.clear()
|
||||
console.log(tag ? gray(`[${tag}]`) : '', ...args)
|
||||
}
|
||||
|
||||
function shorten(url) {
|
||||
return String(url).indexOf(URL) === 0 ? gray(URL) + (url.substr(URL.length) || '/') : url
|
||||
}
|
@ -232,12 +232,12 @@ $pinks: (
|
||||
) !default;
|
||||
|
||||
$hue-maps: (
|
||||
gray: $grays,
|
||||
blue: $blues,
|
||||
green: $greens,
|
||||
yellow: $yellows,
|
||||
orange: $oranges,
|
||||
red: $reds,
|
||||
purple: $purples,
|
||||
pink: $pinks,
|
||||
"gray": $grays,
|
||||
"blue": $blues,
|
||||
"green": $greens,
|
||||
"yellow": $yellows,
|
||||
"orange": $oranges,
|
||||
"red": $reds,
|
||||
"purple": $purples,
|
||||
"pink": $pinks,
|
||||
) !default;
|
||||
|
@ -29,8 +29,6 @@ $border-purple: $purple !default;
|
||||
$border-red: $red !default;
|
||||
$border-red-light: desaturate($red-300, 60%) !default;
|
||||
|
||||
$border-purple: $purple !default;
|
||||
|
||||
$border-yellow: desaturate($yellow-300, 60%) !default;
|
||||
|
||||
$border-gray-dark: $gray-300 !default;
|
||||
@ -55,6 +53,7 @@ $bg-red-light: $red-100 !default;
|
||||
$bg-white: $white !default;
|
||||
$bg-yellow: $yellow-500 !default;
|
||||
$bg-yellow-light: $yellow-200 !default;
|
||||
$bg-yellow-dark: $yellow-700 !default;
|
||||
|
||||
// Text colors
|
||||
$text-blue: $blue-500 !default;
|
||||
@ -68,3 +67,4 @@ $text-purple: $purple !default;
|
||||
$text-pink: $pink-500 !default;
|
||||
$text-red: $red-600 !default;
|
||||
$text-white: $white !default;
|
||||
$text-yellow: $yellow-800 !default;
|
||||
|
@ -2,19 +2,25 @@
|
||||
// stylelint-disable primer/selector-no-utility
|
||||
// stylelint-disable block-opening-brace-space-before, comment-empty-line-before
|
||||
|
||||
/* Add a gray border on all sides */
|
||||
/* Add a gray border on all edges */
|
||||
.border { border: $border !important; }
|
||||
|
||||
/* Add a gray border to the left and right */
|
||||
.border-x {
|
||||
border-right: $border !important;
|
||||
border-left: $border !important;
|
||||
}
|
||||
|
||||
/* Add a gray border to the top and bottom */
|
||||
.border-y {
|
||||
border-top: $border !important;
|
||||
border-bottom: $border !important;
|
||||
}
|
||||
|
||||
/* Remove borders from all sides */
|
||||
.border-0 { border: 0 !important; }
|
||||
|
||||
.border-dashed { border-style: dashed !important; }
|
||||
/* Change the border style to dashed, in conjunction with another utility */
|
||||
.border-dashed {
|
||||
border-style: dashed !important;
|
||||
}
|
||||
|
||||
$edges: (
|
||||
top: (top-left, top-right),
|
||||
@ -23,9 +29,14 @@ $edges: (
|
||||
left: (bottom-left, top-left)
|
||||
);
|
||||
|
||||
/* Responsive gray borders */
|
||||
@each $breakpoint, $variant in $responsive-variants {
|
||||
@include breakpoint($breakpoint) {
|
||||
/* Add a gray border */
|
||||
/* Add a gray border on all sides at/above this breakpoint */
|
||||
.border#{$variant} { border: $border !important; }
|
||||
/* Set the border width to 0 on all sides at/above this breakpoint */
|
||||
.border#{$variant}-0 { border: 0 !important; }
|
||||
|
||||
/* Add a gray border to the top */
|
||||
.border#{$variant}-top { border-top: $border !important; }
|
||||
/* Add a gray border to the right */
|
||||
|
@ -2,6 +2,8 @@
|
||||
// stylelint-disable primer/selector-no-utility
|
||||
// stylelint-disable block-opening-brace-space-before, comment-empty-line-before
|
||||
|
||||
@warn ".text-pending and .bg-pending will be deprecated in 13.0.0. Use .text-yellow and .bg-yellow-dark instead";
|
||||
|
||||
// background colors
|
||||
/* Set the background to $bg-white */
|
||||
.bg-white { background-color: $bg-white !important; }
|
||||
@ -27,6 +29,8 @@
|
||||
.bg-yellow { background-color: $bg-yellow !important; }
|
||||
/* Set the background to $bg-yellow-light */
|
||||
.bg-yellow-light { background-color: $bg-yellow-light !important; }
|
||||
/* Set the background to $bg-yellow-dark */
|
||||
.bg-yellow-dark { background-color: $bg-yellow-dark !important; }
|
||||
/* Set the background to $bg-purple */
|
||||
.bg-purple { background-color: $bg-purple !important; }
|
||||
/* Set the background to $bg-pink */
|
||||
@ -61,6 +65,8 @@
|
||||
.text-gray-dark { color: $text-gray-dark !important; }
|
||||
/* Set the text color to $text-green */
|
||||
.text-green { color: $text-green !important; }
|
||||
/* Set the text color to $text-yellow */
|
||||
.text-yellow { color: $text-yellow !important; }
|
||||
/* Set the text color to $text-orange */
|
||||
.text-orange { color: $text-orange !important; }
|
||||
/* Set the text color to $text-orange-light */
|
||||
@ -74,10 +80,10 @@
|
||||
/* Set the text color to inherit */
|
||||
.text-inherit { color: inherit !important; }
|
||||
|
||||
// Text states
|
||||
// These can probably all be regular utilities
|
||||
// Pending states
|
||||
// This will be deprecated in the future, use .text-yellow instead
|
||||
.text-pending { color: $yellow-800 !important; }
|
||||
// Separate text and background colors in future to improve a11y
|
||||
// This will be deprecated in the future, use .bg-yellow-dark instead
|
||||
.bg-pending { color: $yellow-700 !important; }
|
||||
|
||||
// Link colors
|
||||
|
@ -36,17 +36,11 @@
|
||||
.v-align-baseline { vertical-align: baseline !important; }
|
||||
|
||||
// Overflow utilities
|
||||
.overflow-hidden { overflow: hidden !important; }
|
||||
.overflow-x-hidden { overflow-x: hidden !important; }
|
||||
.overflow-y-hidden { overflow-y: hidden !important; }
|
||||
|
||||
.overflow-auto { overflow: auto !important; }
|
||||
.overflow-x-auto { overflow-x: auto !important; }
|
||||
.overflow-y-auto { overflow-y: auto !important; }
|
||||
|
||||
.overflow-scroll { overflow: scroll !important; }
|
||||
.overflow-x-scroll { overflow-x: scroll !important; }
|
||||
.overflow-y-scroll { overflow-y: scroll !important; }
|
||||
@each $overflow in (visible, hidden, auto, scroll) {
|
||||
.overflow-#{$overflow} { overflow: $overflow !important; }
|
||||
.overflow-x-#{$overflow} { overflow-x: $overflow !important; }
|
||||
.overflow-y-#{$overflow} { overflow-y: $overflow !important; }
|
||||
}
|
||||
|
||||
// Clear floats
|
||||
/* Clear floats around the element */
|
||||
|
@ -1,95 +0,0 @@
|
||||
const {join} = require('path')
|
||||
const fse = require('fs-extra')
|
||||
const globby = require('globby')
|
||||
const test = require('ava')
|
||||
const minimatch = require('minimatch')
|
||||
|
||||
const cwd = process.cwd()
|
||||
const css = require(cwd)
|
||||
const pkg = require(join(cwd, 'package.json'))
|
||||
|
||||
const unique = list => Array.from(new Set(list)).sort()
|
||||
|
||||
/*
|
||||
* These are the regular expressions that match what we
|
||||
* expect to be class name instances in the docs.
|
||||
* Patterns should group the matched class name(s) such that:
|
||||
*
|
||||
* ```js
|
||||
* const [, klass, ] = pattern.exec(content)
|
||||
* ```
|
||||
*/
|
||||
const classPatterns = [
|
||||
// HTML class attributes
|
||||
/class="([^"]+)"/ig,
|
||||
/:class ?=> "([^"]+)"/g,
|
||||
/class: "([^"]+)"/g,
|
||||
// assume that ERB helpers generate an element with the same class
|
||||
/<%= (\w+)\b/g,
|
||||
]
|
||||
|
||||
const whitelistClasses = (pkg.primer ? pkg.primer.class_whitelist || [] : [])
|
||||
.concat('js*')
|
||||
|
||||
const isWhitelisted = klass => {
|
||||
return whitelistClasses.some(glob => minimatch(klass, glob))
|
||||
}
|
||||
|
||||
// Find unique selectors from the cssstats selector list
|
||||
function uniqueSelectors(selectors) {
|
||||
return unique(selectors.map(s => {
|
||||
// split multi-selectors into last class used .foo .bar .baz
|
||||
return s.split(' ').pop()
|
||||
})
|
||||
.filter(s => {
|
||||
// only match exact class selectors
|
||||
return s.match(/^\.[a-z\-_]+$/ig)
|
||||
}))
|
||||
}
|
||||
|
||||
// From the given glob sources array, read the files and return found classnames
|
||||
function getDocumentedClassnames(sources) {
|
||||
return globby(sources)
|
||||
.then(paths => {
|
||||
return Promise.all(paths.map(path => {
|
||||
return fse.readFile(path, 'utf8')
|
||||
.then(content => ({path, content}))
|
||||
}))
|
||||
})
|
||||
.then(files => {
|
||||
return files.reduce((classes, {path, content}) => {
|
||||
classPatterns.forEach(pattern => {
|
||||
let match
|
||||
while (match = pattern.exec(content)) {
|
||||
// get the matched classnames and split by whitespace into classes
|
||||
let klasses = match[1].trim().split(/\s+/)
|
||||
classes.push(...klasses)
|
||||
}
|
||||
})
|
||||
return classes
|
||||
}, [])
|
||||
})
|
||||
.then(classes => unique(classes))
|
||||
}
|
||||
|
||||
const selectors = uniqueSelectors(css.cssstats.selectors.values)
|
||||
let classnames
|
||||
test.before(t => {
|
||||
return getDocumentedClassnames([
|
||||
'docs/*.md',
|
||||
'README.md'
|
||||
])
|
||||
.then(_ => (classnames = _))
|
||||
})
|
||||
|
||||
selectors.forEach(selector => {
|
||||
const klass = selector.replace(/^\./, '')
|
||||
test(`Selector "${selector}" is documented/whitelisted`, t => {
|
||||
t.plan(1)
|
||||
if (isWhitelisted(klass)) {
|
||||
t.pass(`Selector "${selector}" is whitelisted`)
|
||||
} else {
|
||||
t.is(classnames.includes(klass), true, `Selector "${selector}" is not documented`)
|
||||
}
|
||||
})
|
||||
})
|
@ -1,38 +0,0 @@
|
||||
const test = require('ava')
|
||||
const fs = require('fs-extra')
|
||||
const globby = require('globby')
|
||||
const {join} = require('path')
|
||||
|
||||
const {packages} = require('../lerna.json')
|
||||
const year = (new Date()).getFullYear()
|
||||
const yearRegex = new RegExp(`Copyright \\(c\\) ${year} GitHub Inc\\.`)
|
||||
|
||||
test(`LICENSE files have the current year ${year}`, t => {
|
||||
return getPackageGlobs('LICENSE')
|
||||
.then(paths => {
|
||||
t.plan(paths.length)
|
||||
return paths.map(path => {
|
||||
const license = fs.readFileSync(path, 'utf8')
|
||||
return t.regex(license, yearRegex, `The license "${path}" does not include the current year ${year}`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test(`Source header copyrights have the current year ${year}`, t => {
|
||||
return getPackageGlobs('{*.scss,lib/**/*.scss}')
|
||||
.then(paths => {
|
||||
t.plan(paths.length)
|
||||
return paths.map(path => {
|
||||
const source = fs.readFileSync(path, 'utf8')
|
||||
if (source.match(/Copyright \(c\)/)) {
|
||||
return t.regex(source, yearRegex, `The source's header "${path}" does not include the current year ${year}`)
|
||||
} else {
|
||||
return t.true(true)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function getPackageGlobs(glob) {
|
||||
return globby(packages.map(pkg => join(pkg, glob)))
|
||||
}
|
Loading…
Reference in New Issue
Block a user