Skip to content

Commit

Permalink
feat: add CSS stack
Browse files Browse the repository at this point in the history
Introduce the CSS stack to the project,
it generates Lint and Format stages with
Stylelint and Prettier respectively.
Add templates for GitHub workflows.
  • Loading branch information
oesgalha committed Aug 19, 2021
1 parent a4312af commit 64ddeba
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 1 deletion.
57 changes: 57 additions & 0 deletions plugins/stack/_shared/stylelint/mod.test.ts
@@ -0,0 +1,57 @@
import { context } from "../../../../src/plugin/mod.ts";
import { assertEquals, deepMerge, WalkEntry } from "../../../../deps.ts";

import { introspect } from "./mod.ts";

const fakeContext = (
{
withStylelint = true,
devDependencies = true,
} = {},
) => {
return deepMerge(
context,
{
files: {
each: async function* (glob: string): AsyncIterableIterator<WalkEntry> {
if (glob === "**/package.json") {
yield {
name: "package.json",
path: "fake-path",
isFile: true,
isSymlink: false,
isDirectory: false,
};
}
return;
},
// deno-lint-ignore require-await
readJSON: async (path: string): Promise<Record<string, unknown>> => {
const deps = { stylelint: "1.0.0" };
if (!withStylelint) return {};
if (path === "fake-path") {
return devDependencies
? { devDependencies: deps }
: { dependencies: deps };
}
return {};
},
},
},
);
};

Deno.test("Plugins > _shared > Stylelint - at devDependecies", async () => {
const result = await introspect(fakeContext());
assertEquals(result, { name: "stylelint" });
});

Deno.test("Plugins > _shared > Stylelint - at dependecies", async () => {
const result = await introspect(fakeContext({ devDependencies: false }));
assertEquals(result, { name: "stylelint" });
});

Deno.test("Plugins > _shared > Stylelint - not present", async () => {
const result = await introspect(fakeContext({ withStylelint: false }));
assertEquals(result, null);
});
25 changes: 25 additions & 0 deletions plugins/stack/_shared/stylelint/mod.ts
@@ -0,0 +1,25 @@
import { IntrospectFn } from "../../deps.ts";

export interface Stylelint {
name: "stylelint";
}

export const introspect: IntrospectFn<Stylelint | null> = async (context) => {
for await (const file of context.files.each("**/package.json")) {
const packageJson = await context.files.readJSON(file.path);
const packages = {
...(packageJson?.dependencies || {}),
...(packageJson?.devDependencies || {}),
};
const hasStylelint = Object.keys(packages).some((name) =>
name === "stylelint"
);
if (hasStylelint) {
return {
"name": "stylelint",
};
}
}

return null;
};
76 changes: 76 additions & 0 deletions plugins/stack/css/mod.ts
@@ -0,0 +1,76 @@
import { Introspector } from "../deps.ts";
import {
introspect as introspectFormatter,
Prettier,
} from "../_shared/prettier/mod.ts";
import {
introspect as introspectLinter,
Stylelint,
} from "../_shared/stylelint/mod.ts";
import {
introspect as introspectPackageManager,
NodePackageManager,
} from "../_shared/node_package_manager/mod.ts";

// Available package managers
type PackageManager = NodePackageManager | null;
// Available code formatters
type Formatter = Prettier | null;
// Available linters
type Linter = Stylelint | null;

/**
* Introspected information about a project with JavaScript
*/
export default interface CssProject {
/**
* Which package manager is used in the project
*/
packageManager?: PackageManager;
/**
* Which formatter the project uses, if any
*/
formatter?: Formatter;
/**
* Which linter the project uses, if any
*/
linter?: Linter;
}

export const introspector: Introspector<CssProject> = {
detect: async (context) => {
return await context.files.includes("**/*.{c,sc,sa,le}ss");
},
introspect: async (context) => {
const logger = context.getLogger("css");

// Package manager
logger.debug("detecting package manager");
const packageManager = await introspectPackageManager(context);
logger.debug(`detected package manager "${packageManager.name}"`);

// Formatter
logger.debug("detecting formatter");
const formatter = await introspectFormatter(context);
if (formatter !== null) {
logger.debug(`detected formatter "${formatter.name}"`);
} else {
logger.debug("no supported formatter detected");
}

// Linter
logger.debug("detecting linter");
const linter = await introspectLinter(context);
if (linter !== null) {
logger.debug(`detected linter "${linter.name}"`);
} else {
logger.debug("no supported linter detected");
}

return {
packageManager,
formatter,
linter,
};
},
};
6 changes: 5 additions & 1 deletion plugins/stack/mod.ts
@@ -1,16 +1,20 @@
import { introspector as CssIntrospector } from "./css/mod.ts";
import { introspector as JavaScriptIntrospector } from "./javascript/mod.ts";
import { introspector as PythonIntrospector } from "./python/mod.ts";

import type CSSProject from "./css/mod.ts";
import type JavaScriptProject from "./javascript/mod.ts";
import type PythonProject from "./python/mod.ts";

export type ProjectData =
| CSSProject
| JavaScriptProject
| PythonProject;

export type { JavaScriptProject, PythonProject };
export type { CSSProject, JavaScriptProject, PythonProject };

export const introspectors = [
{ name: "css", ...CssIntrospector },
{ name: "javascript", ...JavaScriptIntrospector },
{ name: "python", ...PythonIntrospector },
];
30 changes: 30 additions & 0 deletions templates/github/css/format.yaml
@@ -0,0 +1,30 @@
<% if (it.formatter) { -%>
name: Format CSS
on:
pull_request:
paths:
- '**.css'
- '**.scss'
- '**.sass'
- '**.less'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
cache: '<%= it.packageManager.name %>'

<%_ let installCmd; let runPrefix; -%>
<%_ if (it.packageManager.name === "npm") { -%>
<%_ installCmd = "npm ci" %>
<%_ runPrefix = "npx" %>
<%_ } else { -%>
<%_ installCmd = "yarn" %>
<%_ runPrefix = "yarn" %>
<% } -%>

- run: <%= installCmd %>
- run: <%= runPrefix %> prettier --no-error-on-unmatched-pattern --check "**.css" "**.scss" "**.sass" "**.less"
<% } -%>
30 changes: 30 additions & 0 deletions templates/github/css/lint.yaml
@@ -0,0 +1,30 @@
<% if (it.formatter) { -%>
name: Lint CSS
on:
pull_request:
paths:
- '**.css'
- '**.scss'
- '**.sass'
- '**.less'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
cache: '<%= it.packageManager.name %>'

<%_ let installCmd; let runPrefix; -%>
<%_ if (it.packageManager.name === "npm") { -%>
<%_ installCmd = "npm ci" %>
<%_ runPrefix = "npx" %>
<%_ } else { -%>
<%_ installCmd = "yarn" %>
<%_ runPrefix = "yarn" %>
<% } -%>

- run: <%= installCmd %>
- run: <%= runPrefix %> stylelint "**/*.css" "**/*.scss" "**/*.sass" "**/*.less"
<% } -%>

0 comments on commit 64ddeba

Please sign in to comment.