1668077768
Collection of utility types, complementing TypeScript built-in mapped types and aliases (think "lodash" for static types).
Found it useful? Want more updates?
π Now updated to support TypeScript v3.7 π
TypeScript
.dts-jest
# NPM
npm install utility-types
# YARN
yarn add utility-types
TypeScript support
v3.x.x
- TypeScript v3.1+v2.x.x
- TypeScript v2.8.1+v1.x.x
- TypeScript v2.7.2+Utility-Types is an open-source project created by people investing their time for the benefit of our community.
Issues like bug fixes or feature requests can be very quickly resolved when funded through the IssueHunt platform.
I highly recommend adding a bounty to the issue that you're waiting for to attract some contributors willing to work on it.
We are open for contributions. If you're planning to contribute please make sure to read the contributing guide as it can save you from wasting your time: CONTRIBUTING.md
Table of Contents
SetIntersection<A, B>
SetDifference<A, B>
SetComplement<A, A1>
SymmetricDifference<A, B>
Exclude<A, B>
(built-in)Extract<A, B>
(built-in)NonNullable<T>
(built-in)NonUndefined<T>
FunctionKeys<T>
NonFunctionKeys<T>
MutableKeys<T>
ReadonlyKeys<T>
RequiredKeys<T>
OptionalKeys<T>
Optional<T, K>
Partial<T>
(built-in)DeepPartial<T>
Required<T, K>
DeepRequired<T>
Readonly<T>
(built-in)DeepReadonly<T>
Mutable<T>
Pick<T, K>
(built-in)Omit<T, K>
(built-in)PickByValue<T, ValueType>
PickByValueExact<T, ValueType>
OmitByValue<T, ValueType>
OmitByValueExact<T, ValueType>
Intersection<T, U>
Diff<T, U>
Subtract<T, T1>
Overwrite<T, U>
Assign<T, U>
ValuesType<T>
ReturnType<T>
(built-in)InstanceType<T>
(built-in)PromiseType<T>
Unionize<T>
Brand<T, U>
UnionToIntersection<U>
$Keys<T>
$Values<T>
$ReadOnly<T>
$Diff<T, U>
$PropertyType<T, K>
$ElementType<T, K>
$Call<T>
$Shape<T>
$NonMaybeType<T>
Class<T>
mixed
getReturnOfExpression()
- from TS v2.0 it's better to use type-level ReturnType
insteadPrimitive
Type representing primitive types in JavaScript, and thus TypeScript: string | number | bigint | boolean | symbol | null | undefined
You can test for singular of these types with typeof
isPrimitive
This is a TypeScript Typeguard for the Primitive
type.
This can be useful to control the type of a parameter as the program flows. Example:
const consumer = (param: Primitive[] | Primitive): string => {
if (isPrimitive(param)) {
// typeof param === Primitive
return String(param) + ' was Primitive';
}
// typeof param === Primitive[]
const resultArray = param
.map(consumer)
.map(rootString => '\n\t' + rootString);
return resultArray.reduce((comm, newV) => comm + newV, 'this was nested:');
};
Falsy
Type representing falsy values in TypeScript: false | "" | 0 | null | undefined
Except
NaN
which cannot be represented as a type literal
isFalsy
const consumer = (param: Falsy | string): string => {
if (isFalsy(param)) {
// typeof param === Falsy
return String(param) + ' was Falsy';
}
// typeof param === string
return param.toString();
};
Nullish
Type representing nullish values in TypeScript: null | undefined
isNullish
const consumer = (param: Nullish | string): string => {
if (isNullish(param)) {
// typeof param === Nullish
return String(param) + ' was Nullish';
}
// typeof param === string
return param.toString();
};
SetIntersection<A, B>
(same as Extract)Set intersection of given union types A
and B
Usage:
import { SetIntersection } from 'utility-types';
// Expect: "2" | "3"
type ResultSet = SetIntersection<'1' | '2' | '3', '2' | '3' | '4'>;
// Expect: () => void
type ResultSetMixed = SetIntersection<string | number | (() => void), Function>;
SetDifference<A, B>
(same as Exclude)Set difference of given union types A
and B
Usage:
import { SetDifference } from 'utility-types';
// Expect: "1"
type ResultSet = SetDifference<'1' | '2' | '3', '2' | '3' | '4'>;
// Expect: string | number
type ResultSetMixed = SetDifference<string | number | (() => void), Function>;
SetComplement<A, A1>
Set complement of given union types A
and (it's subset) A1
Usage:
import { SetComplement } from 'utility-types';
// Expect: "1"
type ResultSet = SetComplement<'1' | '2' | '3', '2' | '3'>;
SymmetricDifference<A, B>
Set difference of union and intersection of given union types A
and B
Usage:
import { SymmetricDifference } from 'utility-types';
// Expect: "1" | "4"
type ResultSet = SymmetricDifference<'1' | '2' | '3', '2' | '3' | '4'>;
NonNullable<A>
Exclude null
and undefined
from set A
NonUndefined<A>
Exclude undefined
from set A
Exclude<A, B>
Exclude subset B
from set A
Extract<A, B>
Extract subset B
from set A
FunctionKeys<T>
Get union type of keys that are functions in object type T
Usage:
import { FunctionKeys } from 'utility-types';
type MixedProps = { name: string; setName: (name: string) => void };
// Expect: "setName"
type Keys = FunctionKeys<MixedProps>;
NonFunctionKeys<T>
Get union type of keys that are non-functions in object type T
Usage:
import { NonFunctionKeys } from 'utility-types';
type MixedProps = { name: string; setName: (name: string) => void };
// Expect: "name"
type Keys = NonFunctionKeys<MixedProps>;
MutableKeys<T>
Get union type of keys that are mutable (not readonly) in object type T
Alias: WritableKeys<T>
Usage:
import { MutableKeys } from 'utility-types';
type Props = { readonly foo: string; bar: number };
// Expect: "bar"
type Keys = MutableKeys<Props>;
ReadonlyKeys<T>
Get union type of keys that are readonly in object type T
Usage:
import { ReadonlyKeys } from 'utility-types';
type Props = { readonly foo: string; bar: number };
// Expect: "foo"
type Keys = ReadonlyKeys<Props>;
RequiredKeys<T>
Get union type of keys that are required in object type T
Usage:
import { RequiredKeys } from 'utility-types';
type Props = { req: number; reqUndef: number | undefined; opt?: string; optUndef?: number | undefined; };
// Expect: "req" | "reqUndef"
type Keys = RequiredKeys<Props>;
OptionalKeys<T>
Get union type of keys that are optional in object type T
Usage:
import { OptionalKeys } from 'utility-types';
type Props = { req: number; reqUndef: number | undefined; opt?: string; optUndef?: number | undefined; };
// Expect: "opt" | "optUndef"
type Keys = OptionalKeys<Props>;
Optional<T, K>
From T
make a set of properties by key K
become optional
Usage:
import { Optional } from 'utility-types';
type Props = { name: string; age: number; visible: boolean; };
// Expect: { name?: string; age?: number; visible?: boolean; }
type Props = Optional<Props>
// Expect: { name: string; age?: number; visible?: boolean; }
type Props = Optional<Props, 'age' | 'visible'>;
Pick<T, K>
(built-in)From T
pick a set of properties by key K
Usage:
type Props = { name: string; age: number; visible: boolean };
// Expect: { age: number; }
type Props = Pick<Props, 'age'>;
PickByValue<T, ValueType>
From T
pick a set of properties by value matching ValueType
. (Credit: Piotr Lewandowski)
Usage:
import { PickByValue } from 'utility-types';
type Props = { req: number; reqUndef: number | undefined; opt?: string; };
// Expect: { req: number }
type Props = PickByValue<Props, number>;
// Expect: { req: number; reqUndef: number | undefined; }
type Props = PickByValue<Props, number | undefined>;
PickByValueExact<T, ValueType>
From T
pick a set of properties by value matching exact ValueType
.
Usage:
import { PickByValueExact } from 'utility-types';
type Props = { req: number; reqUndef: number | undefined; opt?: string; };
// Expect: { req: number }
type Props = PickByValueExact<Props, number>;
// Expect: { reqUndef: number | undefined; }
type Props = PickByValueExact<Props, number | undefined>;
Omit<T, K>
From T
remove a set of properties by key K
Usage:
import { Omit } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
// Expect: { name: string; visible: boolean; }
type Props = Omit<Props, 'age'>;
OmitByValue<T, ValueType>
From T
remove a set of properties by value matching ValueType
. (Credit: Piotr Lewandowski)
Usage:
import { OmitByValue } from 'utility-types';
type Props = { req: number; reqUndef: number | undefined; opt?: string; };
// Expect: { reqUndef: number | undefined; opt?: string; }
type Props = OmitByValue<Props, number>;
// Expect: { opt?: string; }
type Props = OmitByValue<Props, number | undefined>;
OmitByValueExact<T, ValueType>
From T
remove a set of properties by value matching exact ValueType
.
Usage:
import { OmitByValueExact } from 'utility-types';
type Props = { req: number; reqUndef: number | undefined; opt?: string; };
// Expect: { reqUndef: number | undefined; opt?: string; }
type Props = OmitByValueExact<Props, number>;
// Expect: { req: number; opt?: string }
type Props = OmitByValueExact<Props, number | undefined>;
Intersection<T, U>
From T
pick properties that exist in U
Usage:
import { Intersection } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
type DefaultProps = { age: number };
// Expect: { age: number; }
type DuplicatedProps = Intersection<Props, DefaultProps>;
Diff<T, U>
From T
remove properties that exist in U
Usage:
import { Diff } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
type DefaultProps = { age: number };
// Expect: { name: string; visible: boolean; }
type RequiredProps = Diff<Props, DefaultProps>;
Subtract<T, T1>
From T
remove properties that exist in T1
(T1
has a subset of the properties of T
)
Usage:
import { Subtract } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
type DefaultProps = { age: number };
// Expect: { name: string; visible: boolean; }
type RequiredProps = Subtract<Props, DefaultProps>;
Overwrite<T, U>
From U
overwrite properties to T
Usage:
import { Overwrite } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
type NewProps = { age: string; other: string };
// Expect: { name: string; age: string; visible: boolean; }
type ReplacedProps = Overwrite<Props, NewProps>;
Assign<T, U>
From U
assign properties to T
(just like object assign)
Usage:
import { Assign } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
type NewProps = { age: string; other: string };
// Expect: { name: string; age: string; visible: boolean; other: string; }
type ExtendedProps = Assign<Props, NewProps>;
ValuesType<T>
Get the union type of all the values in an object, tuple, array or array-like type T
.
Usage:
import { ValuesType } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
// Expect: string | number | boolean
type PropsValues = ValuesType<Props>;
type NumberArray = number[];
// Expect: number
type NumberItems = ValuesType<NumberArray>;
type ReadonlyNumberTuple = readonly [1, 2];
// Expect: 1 | 2
type AnotherNumberUnion = ValuesType<NumberTuple>;
type BinaryArray = Uint8Array;
// Expect: number
type BinaryItems = ValuesType<BinaryArray>;
Partial<T>
Make all properties of object type optional
Required<T, K>
From T
make a set of properties by key K
become required
Usage:
import { Required } from 'utility-types';
type Props = { name?: string; age?: number; visible?: boolean; };
// Expect: { name: string; age: number; visible: boolean; }
type Props = Required<Props>
// Expect: { name?: string; age: number; visible: boolean; }
type Props = Required<Props, 'age' | 'visible'>;
Readonly<T>
Make all properties of object type readonly
Mutable<T>
From T
make all properties become mutable
Alias: Writable<T>
import { Mutable } from 'utility-types';
type Props = {
readonly name: string;
readonly age: number;
readonly visible: boolean;
};
// Expect: { name: string; age: number; visible: boolean; }
Mutable<Props>;
ReturnType<T>
Obtain the return type of a function
InstanceType<T>
Obtain the instance type of a class
Unionize<T>
Disjoin object to form union of objects, each with single property
Usage:
import { Unionize } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
// Expect: { name: string; } | { age: number; } | { visible: boolean; }
type UnionizedType = Unionize<Props>;
PromiseType<T>
Obtain Promise resolve type
Usage:
import { PromiseType } from 'utility-types';
// Expect: string
type Response = PromiseType<Promise<string>>;
DeepReadonly<T>
Readonly that works for deeply nested structures
Usage:
import { DeepReadonly } from 'utility-types';
type NestedProps = {
first: {
second: {
name: string;
};
};
};
// Expect: {
// readonly first: {
// readonly second: {
// readonly name: string;
// };
// };
// }
type ReadonlyNestedProps = DeepReadonly<NestedProps>;
DeepRequired<T>
Required that works for deeply nested structures
Usage:
import { DeepRequired } from 'utility-types';
type NestedProps = {
first?: {
second?: {
name?: string;
};
};
};
// Expect: {
// first: {
// second: {
// name: string;
// };
// };
// }
type RequiredNestedProps = DeepRequired<NestedProps>;
DeepNonNullable<T>
NonNullable that works for deeply nested structure
Usage:
import { DeepNonNullable } from 'utility-types';
type NestedProps = {
first?: null | {
second?: null | {
name?: string | null | undefined;
};
};
};
// Expect: {
// first: {
// second: {
// name: string;
// };
// };
// }
type RequiredNestedProps = DeepNonNullable<NestedProps>;
DeepPartial<T>
Partial that works for deeply nested structures
Usage:
import { DeepPartial } from 'utility-types';
type NestedProps = {
first: {
second: {
name: string;
};
};
};
// Expect: {
// first?: {
// second?: {
// name?: string;
// };
// };
// }
type PartialNestedProps = DeepPartial<NestedProps>;
Brand<T, U>
Define nominal type of U
based on type of T
. Similar to Opaque types in Flow.
Usage:
import { Brand } from 'utility-types';
type USD = Brand<number, "USD">
type EUR = Brand<number, "EUR">
const tax = 5 as USD;
const usd = 10 as USD;
const eur = 10 as EUR;
function gross(net: USD): USD {
return (net + tax) as USD;
}
gross(usd); // ok
gross(eur); // Type '"EUR"' is not assignable to type '"USD"'.
UnionToIntersection<U>
Get intersection type given union type U
Usage:
import { UnionToIntersection } from 'utility-types';
// Expect: { name: string } & { age: number } & { visible: boolean }
UnionToIntersection<{ name: string } | { age: number } | { visible: boolean }>
$Keys<T>
get the union type of all the keys in an object type T
https://flow.org/en/docs/types/utilities/#toc-keys
Usage:
import { $Keys } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
// Expect: "name" | "age" | "visible"
type PropsKeys = $Keys<Props>;
$Values<T>
get the union type of all the values in an object type T
https://flow.org/en/docs/types/utilities/#toc-values
Usage:
import { $Values } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
// Expect: string | number | boolean
type PropsValues = $Values<Props>;
$ReadOnly<T>
get the read-only version of a given object type T
https://flow.org/en/docs/types/utilities/#toc-readonly
Usage:
import { $ReadOnly } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
// Expect: Readonly<{ name: string; age: number; visible: boolean; }>
type ReadOnlyProps = $ReadOnly<Props>;
$Diff<T, U>
get the set difference of a given object types T
and U
(T \ U
)
https://flow.org/en/docs/types/utilities/#toc-diff
Usage:
import { $Diff } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
type DefaultProps = { age: number };
// Expect: { name: string; visible: boolean; }
type RequiredProps = $Diff<Props, DefaultProps>;
$PropertyType<T, K>
get the type of property of an object at a given key K
https://flow.org/en/docs/types/utilities/#toc-propertytype
Usage:
import { $PropertyType } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
// Expect: string
type NameType = $PropertyType<Props, 'name'>;
type Tuple = [boolean, number];
// Expect: boolean
type A = $PropertyType<Tuple, '0'>;
// Expect: number
type B = $PropertyType<Tuple, '1'>;
$ElementType<T, K>
get the type of elements inside of array, tuple or object of type T
, that matches the given index type K
https://flow.org/en/docs/types/utilities/#toc-elementtype
Usage:
import { $ElementType } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
// Expect: string
type NameType = $ElementType<Props, 'name'>;
type Tuple = [boolean, number];
// Expect: boolean
type A = $ElementType<Tuple, 0>;
// Expect: number
type B = $ElementType<Tuple, 1>;
type Arr = boolean[];
// Expect: boolean
type ItemsType = $ElementType<Arr, number>;
type Obj = { [key: string]: number };
// Expect: number
type ValuesType = $ElementType<Obj, string>;
$Call<T>
get the return type of a given expression type
https://flow.org/en/docs/types/utilities/#toc-call
The built-in ReturnType
can be used to accomplish the same goal, although it may have some subtle differences.
Usage:
import { $Call } from 'utility-types';
// Common use-case
const add = (amount: number) => ({ type: 'ADD' as 'ADD', payload: amount });
type AddAction = $Call<typeof add>; // { type: 'ADD'; payload: number }
// Examples migrated from Flow docs
type ExtractPropType<T extends { prop: any }> = (arg: T) => T['prop'];
type Obj = { prop: number };
type PropType = $Call<ExtractPropType<Obj>>; // number
// type Nope = $Call<ExtractPropType<{ nope: number }>>; // Error: argument doesn't match `Obj`.
type ExtractReturnType<T extends () => any> = (arg: T) => ReturnType<T>;
type Fn = () => number;
type FnReturnType = $Call<ExtractReturnType<Fn>>; // number
$Shape<T>
Copies the shape of the type supplied, but marks every field optional.
https://flow.org/en/docs/types/utilities/#toc-shape
Usage:
import { $Shape } from 'utility-types';
type Props = { name: string; age: number; visible: boolean };
// Expect: Partial<Props>
type PartialProps = $Shape<Props>;
$NonMaybeType<T>
Converts a type T
to a non-maybe type. In other words, the values of $NonMaybeType<T>
are the values of T
except for null
and undefined
.
https://flow.org/en/docs/types/utilities/#toc-nonmaybe
Usage:
import { $NonMaybeType } from 'utility-types';
type MaybeName = string | null;
// Expect: string
type Name = $NonMaybeType<MaybeName>;
Class<T>
Given a type T representing instances of a class C, the type Class is the type of the class C
https://flow.org/en/docs/types/utilities/#toc-class * Differs from original Flow's util - implements only constructor part and won't include any static members. Additionally classes in Typescript are not treated as nominal
Usage:
import { Class } from 'utility-types';
function makeStore(storeClass: Class<Store>): Store {
return new storeClass();
}
An arbitrary type that could be anything (same as unknown
)
https://flow.org/en/docs/types/mixed
ts-toolbelt
- Higher type safety for TypeScript$mol_type
- Collection of TypeScript meta types for complex logicAuthor: piotrwitek
Source Code: https://github.com/piotrwitek/utility-types
License: MIT license
1668064680
An entry-point for learning about this architectural model. A place to learn what Jamstack is, for sharing tools, tips, examples and articles. This is also a place to find a local community meetup, or to seek support in starting one of your own.
We've collected a set of videos, presentation, articles and other learning resources about Jamstack. You can contribute content to that pool of resources!
We accept contributions submitted as pull requests.
To contribute a link to a resource:
src/site/_data/resources
folder with a unique and descriptive name. Populate that file according to the structure shown below.src/site/_data/resources
folder. (Image should be a jpeg 600px wide and 400px tall)resource yaml reference:
title: Resource title
date: Publish date (YYYY-MM-DD)
link: the URL of this resource
thumbnailurl: /img/cms/resources/resource-thumbnail.jpg
type:
- article (Help us group and sort the resources by type article|video|presentation)
Before submitting a pull request, or if you are suggesting/contributing code or content changes, it is wise to preview your change in a local build. We've tried to make the process of running a local build as low as possible.
# Clone this repository to your local environment
git clone git@github.com:jamstack/jamstack.org.git
# move in to your local site folder
cd jamstack.org
# install the dependencies
npm install
# run the build and dev server locally
npm start
This site uses TailwindCSS to offer utility CSS classes and provide a rapid means to styling the site. This means that most styling can be done without writing any additional CSS. Instead, utility classes can be added directly to the HTML. This can provide some very rapid development and also offer surprising levels of familiarity for these used to working in this way (since the conventions and classes are not per site.)
While running/developing locally, the npm run start
command will generate the site including the CSS pipeline from Tailwind.
A small number of bespoke CSS rules are provided for efficiency of repeated or global classes. These reside in src/css/tailwind.css
but these should be used sparingly, with most styling taking place in the HTML via Tailwind's utility classes.
During a production build, the CSS pipeline includes a step to remove all unused CSS statements and compress the resultant CSS. For development efficiency, this step is not performed during local development via the npm run start
command. You can preview an optimised production build by running these commands:
# Run a production build
npm run build
# Serve the build locally
npm run start
You can clone this repository and bootstrap it as a test site of your own, complete with the CI/CD build pipeline on Netlify by clicking the button below. (Requires free GitHub and Netlify accounts)
This is the repo for https://jamstack.org
Author: jamstack
Source Code: https://github.com/jamstack/jamstack.org
1667598300
Tailor is a cross-platform static analysis and lint tool for source code written in Apple's Swift programming language. It analyzes your code to ensure consistent styling and help avoid bugs.
Tailor supports Swift 3.0.1 out of the box and helps enforce style guidelines outlined in the The Swift Programming Language, GitHub, Ray Wenderlich, and Coursera style guides. It supports cross-platform usage and can be run on Mac OS X via your shell or integrated with Xcode, as well as on Linux and Windows.
Tailor parses Swift source code using the primary Java target of ANTLR:
ANTLR is a powerful parser generator [ . . . ] widely used in academia and industry to build all sorts of languages, tools, and frameworks.
β About the ANTLR Parser Generator
Getting Started
Requires Java (JRE or JDK) Version 8 or above: Java SE Downloads
brew install tailor
curl -fsSL https://tailor.sh/install.sh | sh
iex (new-object net.webclient).downloadstring('https://tailor.sh/install.ps1')
You may also download Tailor via GitHub Releases, extract the archive, and symlink the tailor/bin/tailor
shell script to a location in your $PATH
.
If your continuous integration server supports Homebrew installation, you may use the following snippet:
before_install:
- brew update
- brew install tailor
In other cases, use this snippet:
Replace ${TAILOR_RELEASE_ARCHIVE}
with the URL of the release you would like to install, e.g. https://github.com/sleekbyte/tailor/releases/download/v0.1.0/tailor.tar
.
before_script:
- wget ${TAILOR_RELEASE_ARCHIVE} -O /tmp/tailor.tar
- tar -xvf /tmp/tailor.tar
- export PATH=$PATH:$PWD/tailor/bin/
Run Tailor with a list of files and directories to analyze, or via Xcode.
$ tailor [options] [--] [[file|directory] ...]
Help for Tailor is accessible via the [-h|--help]
option.
$ tailor -h
Usage: tailor [options] [--] [[file|directory] ...]
Perform static analysis on Swift source files.
Invoking Tailor with at least one file or directory will analyze all Swift files at those paths. If
no paths are provided, Tailor will analyze all Swift files found in '$SRCROOT' (if defined), which
is set by Xcode when run in a Build Phase. Tailor may be set up as an Xcode Build Phase
automatically with the --xcode option.
Options:
-c,--config=<path/to/.tailor.yml> specify configuration file
--debug print ANTLR error messages when parsing error occurs
--except=<rule1,rule2,...> run all rules except the specified ones
-f,--format=<xcode|json|cc|html> select an output format
-h,--help display help
--invert-color invert colorized console output
-l,--max-line-length=<0-999> maximum Line length (in characters)
--list-files display Swift source files to be analyzed
--max-class-length=<0-999> maximum Class length (in lines)
--max-closure-length=<0-999> maximum Closure length (in lines)
--max-file-length=<0-999> maximum File length (in lines)
--max-function-length=<0-999> maximum Function length (in lines)
--max-name-length=<0-999> maximum Identifier name length (in characters)
--max-severity=<error|warning (default)> maximum severity
--max-struct-length=<0-999> maximum Struct length (in lines)
--min-name-length=<1-999> minimum Identifier name length (in characters)
--no-color disable colorized console output
--only=<rule1,rule2,...> run only the specified rules
--purge=<1-999> reduce memory usage by clearing DFA cache after
specified number of files are parsed
--show-rules show description for each rule
-v,--version display version
--xcode=<path/to/project.xcodeproj> add Tailor Build Phase Run Script to Xcode Project
Features
Rule identifiers and "preferred/not preferred" code samples may be found on the Rules page.
Rules may be individually disabled (blacklist) or enabled (whitelist) via the --except
and --only
command-line flags.
tailor --except=brace-style,trailing-whitespace main.swift
tailor --only=redundant-parentheses,terminating-semicolon main.swift
Tailor may be used on Mac OS X via your shell or integrated with Xcode, as well as on Linux and Windows.
Tailor can be integrated with Xcode projects using the --xcode
option.
tailor --xcode /path/to/demo.xcodeproj/
This adds the following Build Phase Run Script to your project's default target.
Tailor's output will be displayed inline within the Xcode Editor Area and as a list in the Log Navigator.
Add a new configuration, say Analyze
, to the project
Modify the active scheme's Analyze
phase to use the new build configuration created above
Tweak the build phase run script to run Tailor only when analyzing the project (β§βB)
if [ "${CONFIGURATION}" = "Analyze" ]; then
if hash tailor 2>/dev/null; then
tailor
else
echo "warning: Please install Tailor from https://tailor.sh"
fi
fi
Tailor uses the following color schemes to format CLI output:
Dark theme (enabled by default)
Light theme (enabled via --invert-color
option)
No color theme (enabled via --no-color
option)
--max-severity
can be used to control the maximum severity of violation messages. It can be set to error
or warning
(by default, it is set to warning
). Setting it to error
allows you to distinguish between lower and higher priority messages. It also fails the build in Xcode, if any errors are reported (similar to how a compiler error fails the build in Xcode). With max-severity
set to warning
, all violation messages are warnings and the Xcode build will never fail.
This setting also affects Tailor's exit code on the command-line, a failing build will exit 1
whereas having warnings only will exit 0
, allowing Tailor to be easily integrated into pre-commit hooks.
Violations on a specific line may be disabled with a trailing single-line comment.
import Foundation; // tailor:disable
Additionally, violations in a given block of code can be disabled by enclosing the block within tailor:off
and tailor:on
comments.
// tailor:off
import Foundation;
import UIKit;
import CoreData;
// tailor:on
class Demo() {
// Define public members here
}
// tailor:off
and // tailor:on
comments must be pairedThe behavior of Tailor can be customized via the .tailor.yml
configuration file. It enables you to
You can tell Tailor which configuration file to use by specifying its file path via the --config
CLI option. By default, Tailor will look for the configuration file in the directory where you will run Tailor from.
The file follows the YAML 1.1 format.
Tailor checks all files found by a recursive search starting from the directories given as command line arguments. However, it only analyzes Swift files that end in .swift
. If you would like Tailor to analyze specific files and directories, you will have to add entries for them under include
. Files and directories can also be ignored through exclude
.
Here is an example that might be used for an iOS project:
include:
- Source # Inspect all Swift files under "Source/"
exclude:
- '**Tests.swift' # Ignore Swift files that end in "Tests"
- Source/Carthage # Ignore Swift files under "Source/Carthage/"
- Source/Pods # Ignore Swift files under "Source/Pods/"
tailor
is run frominclude
/exclude
rules specified in .tailor.yml
to be ignoredTailor allows you to individually disable (blacklist) or enable (whitelist) rules via the except
and only
labels.
Here is an example showcasing how to enable certain rules:
# Tailor will solely check for violations to the following rules
only:
- upper-camel-case
- trailing-closure
- forced-type-cast
- redundant-parentheses
Here is an example showcasing how to disable certain rules:
# Tailor will check for violations to all rules except for the following ones
except:
- parenthesis-whitespace
- lower-camel-case
only
/except
rules specified in .tailor.yml
to be ignoredTailor allows you to specify the output format (xcode
/json
) via the format
label.
Here is an example showcasing how to specify the output format:
# The output format will now be in JSON
format: json
.tailor.yml
to be ignoredTailor allows you to specify the CLI output color schemes via the color
label. To disable colored output, set color
to disable
. To invert the color scheme, set color
to invert
.
Here is an example showcasing how to specify the CLI output color scheme:
# The CLI output will not be colored
color: disable
.tailor.yml
to be ignoredTailor's output format may be customized via the -f
/--format
option. The Xcode formatter is selected by default.
The default xcode
formatter outputs violation messages according to the format expected by Xcode to be displayed inline within the Xcode Editor Area and as a list in the Log Navigator. This format is also as human-friendly as possible on the console.
$ tailor main.swift
********** /main.swift **********
/main.swift:1: warning: [multiple-imports] Imports should be on separate lines
/main.swift:1:18: warning: [terminating-semicolon] Statements should not terminate with a semicolon
/main.swift:3:05: warning: [constant-naming] Global Constant should be either lowerCamelCase or UpperCamelCase
/main.swift:5:07: warning: [redundant-parentheses] Conditional clause should not be enclosed within parentheses
/main.swift:7: warning: [terminating-newline] File should terminate with exactly one newline character ('\n')
Analyzed 1 file, skipped 0 files, and detected 5 violations (0 errors, 5 warnings).
The json
formatter outputs an array of violation messages for each file, and a summary
object indicating the parsing results and the violation counts.
$ tailor -f json main.swift
{
"files": [
{
"path": "/main.swift",
"violations": [
{
"severity": "warning",
"rule": "constant-naming",
"location": {
"line": 1,
"column": 5
},
"message": "Global Constant should be either lowerCamelCase or UpperCamelCase"
}
],
"parsed": true
}
],
"summary": {
"violations": 1,
"warnings": 1,
"analyzed": 1,
"errors": 0,
"skipped": 0
}
}
The html
formatter outputs a complete HTML document that should be written to a file.
tailor -f html main.swift > tailor.html
Developers
Please review the guidelines for contributing to this repository.
./gradlew
may be used instead)External Tools and Libraries
Author: Sleekbyte
Source Code: https://github.com/sleekbyte/tailor
License: MIT license
1667406120
Have trailing slash problems after deploying a static website in production?
This repo explains factually the behavior of:
We also suggest some possible solutions
Let's get more familiar with trailing slash issues.
Common problems:
/myPath
, your host redirects to /myPath/
<a href="otherPath">
are resolved differently (/otherPath
or /myPath/otherPath
depending on the presence/absence of a trailing slashCauses:
/myPath
: /myPath.html
or /myPath/index.html
(the later can lead to an additional trailing slash)Considering this static site:
static
β
βββ file.html
β
βββ folder
β βββ index.html
β
βββ both.html
βββ both
βββ index.html
Behavior of various static hosting providers:
Let's keep this resource up-to-date, and make it exhaustive together.
Author: Slorber
Source Code: https://github.com/slorber/trailing-slash-guide
License: MIT license
1666232580
PMD is a source code analyzer. It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth. It supports many languages. It can be extended with custom rules. It uses JavaCC and Antlr to parse source files into abstract syntax trees (AST) and runs rules against them to find violations. Rules can be written in Java or using a XPath query.
It supports Java, JavaScript, Salesforce.com Apex and Visualforce, Modelica, PLSQL, Apache Velocity, XML, XSL, Scala.
Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code in C/C++, C#, Dart, Fortran, Go, Groovy, Java, JavaScript, JSP, Kotlin, Lua, Matlab, Modelica, Objective-C, Perl, PHP, PLSQL, Python, Ruby, Salesforce.com Apex, Scala, Swift, Visualforce and XML.
In the future we hope to add support for data/control flow analysis and automatic (quick) fixes where it makes sense.
Download the latest binary zip from the releases and extract it somewhere.
Execute bin/run.sh pmd
or bin\pmd.bat
.
See also Getting Started
Demo:
This shows how PMD can detect for loops, that can be replaced by for-each loops.
There are plugins for Maven and Gradle as well as for various IDEs. See Tools / Integrations
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Our latest source of PMD can be found on GitHub. Fork us!
The rule designer is developed over at pmd/pmd-designer. Please see its README for developer documentation.
Become a financial contributor and help us sustain our community. Contribute
This project follows the all-contributors specification. Contributions of any kind welcome!
See credits for the complete list.
Author: pmd
Source Code: https://github.com/pmd/pmd
License: View license
1665851160
Static sites with superpowers
Staticman is a Node.js application that receives user-generated content and uploads it as data files to a GitHub and/or GitLab repository. In practice, this allows you to have dynamic content (e.g. blog post comments) as part of a fully static website, as long as your site automatically deploys on every push to GitHub and/or GitLab, as seen on GitHub Pages, GitLab Pages, Netlify and others.
It consists of a small web service that handles the POST
requests from your forms, runs various forms of validation and manipulation defined by you and finally pushes them to your repository as data files. You can choose to enable moderation, which means files will be pushed to a separate branch and a pull request will be created for your approval, or disable it completely, meaning that files will be pushed to the main branch automatically.
You can download and run the Staticman API on your own infrastructure. The easiest way to get a personal Staticman API instance up and running is to use the free tier of Heroku. If deploying to Heroku you can simply click the button below and enter your config variables directly into Heroku as environment variables.
NOTE: The below steps are not required if deploying to Heroku. To deploy to Heroku, click the above deploy button and enter your configuration variables in the Heroku Dashboard.
Clone the repository and install the dependencies via npm.
git clone git@github.com:eduardoboucas/staticman.git
cd staticman
npm install
Create a development config file from the sample file.
cp config.sample.json config.development.json
Edit the newly-created config file with your GitHub and/or GitLab access token, SSH private key and the port to run the server. Click here for the list of available configuration parameters.
Start the server.
npm start
Each environment, determined by the NODE_ENV
environment variable, requires its own configuration file. When you're ready to push your Staticman API live, create a config.production.json
file before deploying.
Check this guide if you're using Docker.
Staticman runs as a bot using a GitHub and/or GitLab account, as opposed to accessing your account using the traditional OAuth flow. This means that you can give it access to just the repositories you're planning on using it on, instead of exposing all your repositories.
To add Staticman to a repository, you need to add the bot as a collaborator with write access to the repository and ask the bot to accept the invite by firing a GET
request to this URL:
http://your-staticman-url/v2/connect/GITHUB-USERNAME/GITHUB-REPOSITORY
Staticman will look for a config file. For the deprecated v1
endpoints, this is a _config.yml
with a staticman
property inside; for v2
endpoints, Staticman looks for a staticman.yml
file at the root of the repository.
For a list of available configuration parameters, please refer to the documentation page.
Would you like to contribute to Staticman? That's great! Here's how:
npm test
Author: Eduardoboucas
Source Code: https://github.com/eduardoboucas/staticman
License: MIT license
1665741120
Phan is a static analyzer for PHP that prefers to minimize false-positives. Phan attempts to prove incorrectness rather than correctness.
Phan looks for common issues and will verify type compatibility on various operations when type information is available or can be deduced. Phan has a good (but not comprehensive) understanding of flow control and can track values in a few use cases (e.g. arrays, integers, and strings).
Getting Started
The easiest way to use Phan is via Composer.
composer require phan/phan
With Phan installed, you'll want to create a .phan/config.php
file in your project to tell Phan how to analyze your source code. Once configured, you can run it via ./vendor/bin/phan
.
Phan depends on PHP 7.2+ with the php-ast extension (1.0.10+ is preferred) and supports analyzing PHP version 7.0-7.4 syntax. Installation instructions for php-ast can be found here. (Phan can be used without php-ast by using the CLI option --allow-polyfill-parser
, but there are slight differences in the parsing of doc comments)
The Wiki has more information about using Phan.
Features
Phan is able to perform the following kinds of analysis:
object
, void
, iterable
, ?T
, [$x] = ...;
, negative string offsets, multiple exception catches, etc.)--dead-code-detection
)--unused-variable-detection
)--redundant-condition-detection
)use
statements. These and a few other issue types can be automatically fixed with --automatic-fix
.@template
).int[]
, UserObject[]
, array<int,UserObject>
, etc..array{key:string,otherKey:?stdClass}
, etc. (internally and in PHPDoc tags) This also supports indicating that fields of an array shape are optional via array{requiredKey:string,optionalKey?:string}
(useful for @param
)@deprecated
annotation for deprecating classes, methods and functions@internal
annotation for elements (such as a constant, function, class, class constant, property or method) as internal to the package in which it's defined.@suppress <ISSUE_TYPE>
annotations for suppressing issues.@property <union_type> <variable_name>
)@method <union_type> <method_name>(<union_type> <param1_name>)
)class_alias
annotations (experimental, off by default)@phan-closure-scope
(example)array_map
, array_filter
, and other internal array functions.pcntl
)See Phan Issue Types for descriptions and examples of all issues that can be detected by Phan. Take a look at the \Phan\Issue to see the definition of each error type.
Take a look at the Tutorial for Analyzing a Large Sloppy Code Base to get a sense of what the process of doing ongoing analysis might look like for you.
Phan can be used from various editors and IDEs for its error checking, "go to definition" support, etc. via the Language Server Protocol. Editors and tools can also request analysis of individual files in a project using the simpler Daemon Mode.
See the tests directory for some examples of the various checks.
Phan is imperfect and shouldn't be used to prove that your PHP-based rocket guidance system is free of defects.
Additional analysis features have been provided by plugins.
{ throw new Exception("Message"); return $value; }
)*printf()
format strings against the provided arguments (as well as checking for common errors)preg_*()
are valid@suppress
annotations that are no longer needed.Example: Phan's plugins for self-analysis.
Usage
After installing Phan, Phan needs to be configured with details on where to find code to analyze and how to analyze it. The easiest way to tell Phan where to find source code is to create a .phan/config.php
file. A simple .phan/config.php
file might look something like the following.
<?php
/**
* This configuration will be read and overlaid on top of the
* default configuration. Command line arguments will be applied
* after this file is read.
*/
return [
// Supported values: `'5.6'`, `'7.0'`, `'7.1'`, `'7.2'`, `'7.3'`, `'7.4'`, `null`.
// If this is set to `null`,
// then Phan assumes the PHP version which is closest to the minor version
// of the php executable used to execute Phan.
"target_php_version" => null,
// A list of directories that should be parsed for class and
// method information. After excluding the directories
// defined in exclude_analysis_directory_list, the remaining
// files will be statically analyzed for errors.
//
// Thus, both first-party and third-party code being used by
// your application should be included in this list.
'directory_list' => [
'src',
'vendor/symfony/console',
],
// A directory list that defines files that will be excluded
// from static analysis, but whose class and method
// information should be included.
//
// Generally, you'll want to include the directories for
// third-party code (such as "vendor/") in this list.
//
// n.b.: If you'd like to parse but not analyze 3rd
// party code, directories containing that code
// should be added to the `directory_list` as
// to `exclude_analysis_directory_list`.
"exclude_analysis_directory_list" => [
'vendor/'
],
// A list of plugin files to execute.
// Plugins which are bundled with Phan can be added here by providing their name
// (e.g. 'AlwaysReturnPlugin')
//
// Documentation about available bundled plugins can be found
// at https://github.com/phan/phan/tree/master/.phan/plugins
//
// Alternately, you can pass in the full path to a PHP file
// with the plugin's implementation (e.g. 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php')
'plugins' => [
// checks if a function, closure or method unconditionally returns.
// can also be written as 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php'
'AlwaysReturnPlugin',
'DollarDollarPlugin',
'DuplicateArrayKeyPlugin',
'DuplicateExpressionPlugin',
'PregRegexCheckerPlugin',
'PrintfCheckerPlugin',
'SleepCheckerPlugin',
// Checks for syntactically unreachable statements in
// the global scope or function bodies.
'UnreachableCodePlugin',
'UseReturnValuePlugin',
'EmptyStatementListPlugin',
'LoopVariableReusePlugin',
],
];
Take a look at Creating a Config File and Incrementally Strengthening Analysis for more details.
Running phan --help
will show usage information and command-line options.
Phan reads and understands most PHPDoc type annotations including Union Types (like int|MyClass|string|null
) and generic array types (like int[]
or string[]|MyClass[]
or array<int,MyClass>
).
Take a look at Annotating Your Source Code and About Union Types for some help getting started with defining types in your code.
Phan supports (int|string)[]
style annotations, and represents them internally as int[]|string[]
(Both annotations are treated like array which may have integers and/or strings). When you have arrays of mixed types, just use array
.
The following code shows off the various annotations that are supported.
/**
* @return void
*/
function f() {}
/** @deprecated */
class C {
/** @var int */
const C = 42;
/** @var string[]|null */
public $p = null;
/**
* @param int|null $p
* @return string[]|null
*/
public static function f($p) {
if (is_null($p)) {
return null;
}
return array_map(
/** @param int $i */
function($i) {
return "thing $i";
},
range(0, $p)
);
}
}
Just like in PHP, any type can be nulled in the function declaration which also means a null is allowed to be passed in for that parameter.
Phan checks the type of every single element of arrays (Including keys and values). In practical terms, this means that [$int1=>$int2,$int3=>$int4,$int5=>$str6]
is seen as array<int,int|string>
, which Phan represents as array<int,int>|array<int,string>
. [$strKey => new MyClass(), $strKey2 => $unknown]
will be represented as array<string,MyClass>|array<string,mixed>
.
[12,'myString']
will be represented internally as array shapes such as array{0:12,1:'myString'}
Generating a file list
This static analyzer does not track includes or try to figure out autoloader magic. It treats all the files you throw at it as one big application. For code encapsulated in classes this works well. For code running in the global scope it gets a bit tricky because order matters. If you have an index.php
including a file that sets a bunch of global variables and you then try to access those after the include(...)
in index.php
the static analyzer won't know anything about these.
In practical terms this simply means that you should put your entry points and any files setting things in the global scope at the top of your file list. If you have a config.php
that sets global variables that everything else needs, then you should put that first in the list followed by your various entry points, then all your library files containing your classes.
Development
Take a look at Developer's Guide to Phan for help getting started hacking on Phan.
When you find an issue, please take the time to create a tiny reproducing code snippet that illustrates the bug. And once you have done that, fix it. Then turn your code snippet into a test and add it to tests then ./test
and send a PR with your fix and test. Alternatively, you can open an Issue with details.
To run Phan's unit tests, just run ./test
.
To run all of Phan's unit tests and integration tests, run ./tests/run_all_tests.sh
Code of Conduct
We are committed to fostering a welcoming community. Any participant and contributor is required to adhere to our Code of Conduct.
Online Demo
This requires an up to date version of Firefox/Chrome and at least 4 GB of free RAM. (this is a 10 MB download)
Run Phan entirely in your browser.
Author: Phan
Source Code: https://github.com/phan/phan
License: Unknown and 3 other licenses found
1665093600
Animated plots is a package for making animated and static plots. It is built on top of [SFML.jl] (zyedidia/SFML.jl) and allows for fast plotting of functions and variables over time.
Installation
Make sure you have SFML and CSFML installed (see the SFML [installation instructions] (zyedidia/SFML.jl#installation) for more information)
julia> Pkg.clone("https://github.com/zyedidia/AnimatedPlots.jl")
Usage
The easiest way to plot a function is to use the plot
function:
julia> plot(sin)
julia> close(current_window())
A StaticGraph
object can also be passed to plot
if you want to be able to modify the graph afterward (such as changing the color or line thickness)
julia> sin_graph = StaticGraph(sin, thickness=5, color=SFML.blue) # thickness and color
julia> plot(sin_graph)
julia> sin_graph.color = SFML.green
julia> plot(cos)
julia> close(current_window())
You can use the AnimatedGraph
to make animated plots.
julia> animated_sin = AnimatedGraph(sin)
julia> plot(animated_sin)
julia> animated_cos = AnimatedGraph(cos, color=SFML.blue, startx=-10)
julia> animated_cos.speed = 3 # Speed in units per second
julia> plot(animated_cos)
julia> follow(animated_cos) # have the camera follow the plot
See examples/double_pendulum.jl
for an advanced showcase of how to integrate an animated plot into an SFML application
AnimatedPlots supports creating images and gifs of your plots. Creating gifs may take a while, only close your program after it says Created gif file.gif
. In addition, you must have [imagemagick] (http://www.imagemagick.org/script/binary-releases.php) installed in order to make gifs (most package managers provide it).
julia> screenshot("my_screenshot.png") # Take a screenshot and save it to my_screenshot.png
julia> make_gif(300, 300, 10, "MyGif.gif", 0.06) # Create a gif with width, height, duration (in seconds), filename, and delay (the delay between each frame in seconds)
Author: Zyedidia
Source Code: https://github.com/zyedidia/AnimatedPlots.jl
License: View license
1663737660
In today's post we will learn about 10 Popular PHP Libraries for Static Analysis.
What is Static Analysis?
Static analysis is a method of debugging that is done by automatically examining the source code without having to execute the program. This provides developers with an understanding of their code base and helps ensure that it is compliant, safe, and secure.
Table of contents:
A static analysis engine for PHP.
The Exakat Engine is an automated code reviewing engine for PHP.
Copy-paste the following code in your terminal. This was tester on OSX and Linux-debian.
mkdir exakat
cd exakat
curl -o exakat.phar https://www.exakat.io/versions/index.php?file=latest
curl -o apache-tinkerpop-gremlin-server-3.4.12-bin.zip https://www.exakat.io/versions/apache-tinkerpop-gremlin-server-3.4.12-bin.zip
unzip apache-tinkerpop-gremlin-server-3.4.12-bin.zip
mv apache-tinkerpop-gremlin-server-3.4.12 tinkergraph
rm -rf apache-tinkerpop-gremlin-server-3.4.12-bin.zip
# Optional : install neo4j engine.
cd tinkergraph
./bin/gremlin-server.sh install org.apache.tinkerpop neo4j-gremlin 3.4.12
cd ..
php exakat.phar doctor
Phar is the recommended installation process.
The Exakat engine is distributed as a phar archive. Phar contains all the needed PHP code to run it.
The rest of the installation (Gremlin-server) is detailled in the installation documentation.
The quick installation guide is the following (command line, MacOS. See docs for more options):
mkdir exakat
cd exakat
curl -o exakat.phar https://www.exakat.io/versions/index.php?file=latest
curl -o apache-tinkerpop-gremlin-server-3.4.12-bin.zip https://www.exakat.io/versions/apache-tinkerpop-gremlin-server-3.4.12-bin.zip
unzip apache-tinkerpop-gremlin-server-3.4.12-bin.zip
mv apache-tinkerpop-gremlin-server-3.4.12 tinkergraph
rm -rf apache-tinkerpop-gremlin-server-3.4.12-bin.zip
# Optional : install neo4j engine.
cd tinkergraph
./bin/gremlin-server.sh install org.apache.tinkerpop neo4j-gremlin 3.4.12
cd ..
php exakat.phar doctor
The docker usage is detailled in the installation documentation.
docker pull exakat/exakat:latest
A static code analysis tool that helps to enforce rules for dependencies between software layers.
Deptrac is a static code analysis tool for PHP that helps you communicate, visualize and enforce architectural decisions in your projects. You can freely define your architectural layers over classes and which rules should apply to them.
For example, you can use Deptrac to ensure that bundles/modules/extensions in your project are truly independent of each other to make them easier to reuse.
Deptrac can be used in a CI pipeline to make sure a pull request does not violate any of the architectural rules you defined. With the optional Graphviz formatter you can visualize your layers, rules and violations.
You can install Deptrac via Composer. We recommend using the deptrac-shim package for this:
composer require --dev qossmic/deptrac-shim
Alternatively, you can also use Phive or download the binary attached to each release on GitHub. We strongly advise against using the deptrac package directly as a composer dependency. We update dependencies regularly, which might cause disruptions in your project.
Once you have downloaded the phar file, you will need to create a configuration file, where you define your layers and communication ruleset. When you have this file, you can analyse your code by running the analyse command:
php deptrac.phar
# which is equivalent to
php deptrac.phar analyse --config-file=deptrac.yaml
In order to run Deptrac you need at least PHP 8.1.
You can analyse projects that require an older PHP version as long as nikic/php-parser can parse it.
Deptrac is in active development. We are looking for your suggestions and help to make it better.
Feel free to open an issue if you encounter bugs, have suggestions or would like to add a new feature to Deptrac.
Please feel free to improve this documentation, fix bugs, or work on a suggested feature by making a pull request on GitHub. Don't hesitate to ask for support, if you need help at any point.
The Contribution Guide in the documentation contains some advice for making a pull request with code changes.
If you are professional and polite then everything will be alright.
Please don't be inconsiderate or mean, or anything in between.
A code analysis tool using Graph Theory.
Ok guyz, you have a master degree in Graph Theory, you follow Law of Demeter and you live on S.O.L.I.D principles ?
Let's have some Fun ! (^Ο^)
Download the PHAR : mondrian.phar
Try to run a simple command with a few files (or a small part of a project)
$ mondrian.phar digraph /home/dev/project
This command produces a DOT file for GraphViz. Other formats are available :
$ php mondrian.php d --ignore=tests --ignore=vendor --format=html ./MyPhpProject/
Note: The generated html file does not require any dependencies nor a connection.
Running unit tests with PHPUnit
$ phpunit.phar
Building the documentation with phpDocumentor
$ phpDocumentor.phar
Building mondrian.phar from the sources with box2
$ box.phar b
A static analyzer based on PHP 7+ and the php-ast extension.
Phan is a static analyzer for PHP that prefers to minimize false-positives. Phan attempts to prove incorrectness rather than correctness.
Phan looks for common issues and will verify type compatibility on various operations when type information is available or can be deduced. Phan has a good (but not comprehensive) understanding of flow control and can track values in a few use cases (e.g. arrays, integers, and strings).
Getting Started
The easiest way to use Phan is via Composer.
composer require phan/phan
With Phan installed, you'll want to create a .phan/config.php
file in your project to tell Phan how to analyze your source code. Once configured, you can run it via ./vendor/bin/phan
.
Phan 5 depends on PHP 7.2+ with the php-ast extension (1.0.16+ is preferred) and supports analyzing PHP version 7.0-8.1 syntax. Installation instructions for php-ast can be found here. (Phan can be used without php-ast by using the CLI option --allow-polyfill-parser
, but there are slight differences in the parsing of doc comments)
The Wiki has more information about using Phan.
Features
Phan is able to perform the following kinds of analysis:
object
, void
, iterable
, ?T
, [$x] = ...;
, negative string offsets, multiple exception catches, etc.)--dead-code-detection
)--unused-variable-detection
)--redundant-condition-detection
)use
statements. These and a few other issue types can be automatically fixed with --automatic-fix
.@template
).int[]
, UserObject[]
, array<int,UserObject>
, etc..array{key:string,otherKey:?stdClass}
, etc. (internally and in PHPDoc tags) This also supports indicating that fields of an array shape are optional via array{requiredKey:string,optionalKey?:string}
(useful for @param
)@deprecated
annotation for deprecating classes, methods and functions@internal
annotation for elements (such as a constant, function, class, class constant, property or method) as internal to the package in which it's defined.@suppress <ISSUE_TYPE>
annotations for suppressing issues.@property <union_type> <variable_name>
)@method <union_type> <method_name>(<union_type> <param1_name>)
)class_alias
annotations (experimental, off by default)@phan-closure-scope
(example)array_map
, array_filter
, and other internal array functions.pcntl
)Easy to use architecture testing tool for PHP.
PHP Architecture Tester is a static analysis tool to verify architectural requirements.
It provides a natural language abstraction to define your own architectural rules and test them against your software. You can also integrate phpat easily into your toolchain.
There are four groups of supported assertions: Dependency, Inheritance, Composition and Mixin.
βΉοΈ Check out the section WHAT TO TEST to see some examples of typical use cases.
Just require phpat with Composer:
composer require --dev phpat/phpat
Manual download
If you have dependency conflicts, you can also download the latest PHAR file from Releases.
You will have to use it executing php phpat.phar phpat.yaml
and declare your tests in XML or YAML.
You will need to setup a minimum configuration:
# phpat.yaml
src:
path: src/
tests:
path: tests/architecture/
Complete list of options
Name | Description | Default |
---|---|---|
src path | The root path of your application | no default |
src include | Files you want to be tested excluding the rest | all files |
src exclude | Files you want to be excluded in the tests | no files |
composer $ALIAS json | Path of your composer.json file (multiple) | main json |
composer $ALIAS lock | Path of your composer.lock file (multiple) | main lock |
tests path | The path where your tests are | no default |
tests baseline | Path to a generated baseline file | no default |
options verbosity | Output verbosity level (-1/0/1/2) | 0 |
options php-version | PHP version of the src code (x.x.x) | PHP_VERSION |
options ignore-docblocks | Ignore relations on docblocks (T/F) | false |
options ignore-php-extensions | Ignore relations to core and extensions classes (T/F) | true |
--generate-baseline | Option to generate a json baseline file (null/filename) | false |
A PHP compatibility checker for PHP CodeSniffer.
require-dev
section of your composer.json
file."require-dev": {
"phpcompatibility/php-compatibility": "*"
},
"prefer-stable" : true
If PHPCompatibility is the only external PHP CodeSniffer standard you use, you can add the following to your composer.json
file to automatically run the necessary command:
"scripts": {
"post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility",
"post-update-cmd" : "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility"
}
Alternatively - and strongly recommended if you use more than one external PHP CodeSniffer standard - you can use any of the following Composer plugins to handle this for you.
Just add the Composer plugin you prefer to the require-dev
section of your composer.json
file.
As a last alternative in case you use a custom ruleset, and only if you use PHP CodeSniffer version 2.6.0 or higher, you can tell PHP CodeSniffer the path to the PHPCompatibility standard by adding the following snippet to your custom ruleset:
<config name="installed_paths" value="vendor/phpcompatibility/php-compatibility" />
composer update --lock
to install both PHP CodeSniffer, the PHPCompatibility coding standard and - optionally - the Composer plugin../vendor/bin/phpcs -i
on the command line. PHPCompatibility should be listed as one of the available standards../vendor/bin/phpcs -p . --standard=PHPCompatibility
Install PHP CodeSniffer via your preferred method.
PHP CodeSniffer offers a variety of installation methods to suit your work-flow: Composer, PEAR, a Phar file, zipped/tarred release archives or checking the repository out using Git.
Pro-tip: Register the path to PHPCS in your system $PATH
environment variable to make the phpcs
command available from anywhere in your file system.
Download the latest PHPCompatibility release and unzip/untar it into an arbitrary directory.
You can also choose to clone the repository using git to easily update your install regularly.
Add the path to the directory in which you placed your copy of the PHPCompatibility repo to the PHP CodeSniffer configuration using the below command from the command line:
phpcs --config-set installed_paths /path/to/PHPCompatibility
I.e. if you placed the PHPCompatibility
repository in the /my/custom/standards/PHPCompatibility
directory, you will need to add that directory to the PHP CodeSniffer installed_paths
configuration variable.
Warning: β οΈ The installed_paths
command overwrites any previously set installed_paths
. If you have previously set installed_paths
for other external standards, run phpcs --config-show
first and then run the installed_paths
command with all the paths you need separated by commas, i.e.:
phpcs --config-set installed_paths /path/1,/path/2,/path/3
Pro-tip: Alternatively, in case you use a custom ruleset and only if you use PHP CodeSniffer version 2.6.0 or higher, you can tell PHP CodeSniffer the path to the PHPCompatibility standard(s) by adding the following snippet to your custom ruleset:
<config name="installed_paths" value="/path/to/PHPCompatibility" />
Verify that the PHPCompatibility standard is registered correctly by running phpcs -i
on the command line. PHPCompatibility should be listed as one of the available standards.
Now you can use the following command to inspect your code:
phpcs -p . --standard=PHPCompatibility
Like with any PHP CodeSniffer standard, you can add PHPCompatibility to a custom PHP CodeSniffer ruleset.
<?xml version="1.0"?>
<ruleset name="Custom ruleset">
<description>My rules for PHP CodeSniffer</description>
<!-- Run against the PHPCompatibility ruleset -->
<rule ref="PHPCompatibility"/>
<!-- Run against a second ruleset -->
<rule ref="PSR2"/>
</ruleset>
You can also set the testVersion
from within the ruleset:
<!-- Check for cross-version support for PHP 5.6 and higher. -->
<config name="testVersion" value="5.6-"/>
Other advanced options, such as changing the message type or severity of select sniffs, as described in the PHPCS Annotated ruleset wiki page are, of course, also supported.
testVersion
in the ruleset versus command-lineIn PHPCS 3.2.0 and lower, once you set the testVersion
in the ruleset, you could not overrule it from the command-line anymore. Starting with PHPCS 3.3.0, a testVersion
set via the command-line will overrule the testVersion
in the ruleset.
This allows for more flexibility when, for instance, your project needs to comply with PHP 5.5-
, but you have a bootstrap file which needs to be compatible with PHP 5.2-
.
A tool to create customisable dependency graphs.
PhpDependencyAnalysis is an extendable static code analysis for object-oriented PHP-Projects to generate dependency graphs
from abstract datatypes (Classes, Interfaces and Traits) based on namespaces
. Dependencies can be aggregated to build graphs for several levels, like Package-Level or Layer-Level. Each dependency can be verified to a defined architecture.
docker pull mamuz/phpda
NOTE: For graph creation GraphViz
is required on your machine, which is an open source graph visualization software and available for the most platforms.
$ composer require --dev mamuz/php-dependency-analysis
Since version 2.0.0 not supported anymore.
Return Type Declarations
and Anonymous Classes
Phpda can run out of the box by using a prepared configuration
. As you can see configuration is defined by a YAML
file.
To provide your own configuration create a yml file, e.g. located in ./phpda.yml
:
mode: 'usage'
source: './src'
filePattern: '*.php'
ignore: 'tests'
formatter: 'PhpDA\Writer\Strategy\Svg'
target: './phpda.svg'
groupLength: 1
visitor:
- PhpDA\Parser\Visitor\TagCollector
- PhpDA\Parser\Visitor\SuperglobalCollector
visitorOptions:
PhpDA\Parser\Visitor\Required\DeclaredNamespaceCollector: {minDepth: 2, sliceLength: 2}
PhpDA\Parser\Visitor\Required\MetaNamespaceCollector: {minDepth: 2, sliceLength: 2}
PhpDA\Parser\Visitor\Required\UsedNamespaceCollector: {minDepth: 2, sliceLength: 2}
PhpDA\Parser\Visitor\TagCollector: {minDepth: 2, sliceLength: 2}
Perform an analysis with that configuration:
$ docker run --rm -v $PWD:/app mamuz/phpda
Read the Configuration-Chapter to get knowledge about all available options.
A static metric library.
PhpMetrics provides metrics about PHP project and classes, with beautiful and readable HTML report.
Follow the quick start guide to get started. composer require phpmetrics/phpmetrics --dev php ./vendor/bin/phpmetrics --report-html=myreport
Then open the generated ./myreport/index.html
file in your browser.
You can use a configuration file to customize the report, add options, configure rules for Continuous Integration, etc.
You'll find detailed list of metrics in documentation, or running php ./vendor/bin/phpmetrics --metrics
A static analyzer for PHP version migration.
This is a static analyzer for PHP version migration and compatibility checking.
It can suppose your current code running under the new version of PHP then do checking, and provide advice and treatment.
And it can simplify the process of upgrading PHP. Its goal is instead of manual checking.
Features:
Compare to the similar project PHP Compatibility
PHP Compatibility
is a set of sniffs forPHP_CodeSniffer
, therefore it lacks flexibility and can not checks more changes. just objective comparison
Notice: this project is in beta stage, feel free to report any issues.
You can download a executable Phar file
wget https://github.com/monque/PHP-Migration/releases/download/v0.2.2/phpmig.phar
Use the following command to check PHP file
php phpmig.phar sample.php
Suppose these code stored in sample.php
<?php
// Fatal error: Only variables can be passed by reference
array_shift(array(1, 2));
sort(array(1, 2, 3));
// __DIR__ is pre-defined
define('__DIR__', dirname(__FILE__));
// Fatal error: Cannot redeclare class_alias()
function class_alias() {}
// This is fine
if (!function_exists('class_alias')) {
function class_alias() {}
}
// Fatal error: Call-time pass-by-reference has been removed
array_map('trim', &$_SERVER);
// Fatal error: 'break' operator with non-constant operand is no longer supported
while (true) {
break $a;
}
// Fatal error: Cannot re-assign auto-global variable _GET
function ohno($_GET) {}
// Array keys won't be overwritten when defining an array as a property of a class via an array literal
class C {
const ONE = 1;
public $array = [
self::ONE => 'foo',
'bar',
'quux',
];
}
// set_exception_handler() is no longer guaranteed to receive Exception objects
set_exception_handler(function (Exception $e) { });
// Changes to the handling of indirect variables, properties, and methods
echo $$foo['bar']['baz'];
// foreach no longer changes the internal array pointer
foreach ($list as &$row) {
current($list);
}
Output report Each columns means: Line Number, Level, Identified, Version, Message
File: sample.php
--------------------------------------------------------------------------------
Found 11 spot(s), 10 identified
--------------------------------------------------------------------------------
3 | FATAL | * | 5.3.0 | Only variables can be passed by reference
4 | FATAL | * | 5.3.0 | Only variables can be passed by reference
7 | WARNING | * | 5.3.0 | Constant "__DIR__" already defined
10 | FATAL | * | 5.3.0 | Cannot redeclare class_alias()
18 | FATAL | * | 5.4.0 | Call-time pass-by-reference has been removed
22 | FATAL | * | 5.4.0 | break operator with non-constant operand is no longer supported
26 | FATAL | * | 5.4.0 | Cannot re-assign auto-global variable
31 | WARNING | | 5.6.0 | Array key may be overwritten when defining as a property and using constants
39 | WARNING | * | 7.0.0 | set_exception_handler() is no longer guaranteed to receive Exception objects
42 | WARNING | * | 7.0.0 | Different behavior between PHP 5/7
46 | NOTICE | * | 7.0.0 | foreach no longer changes the internal array pointer
--------------------------------------------------------------------------------
The third field
Identified
will be explained at bottom.
A PHP Static Analysis Tool.
PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code can be checked before you run the actual line.
Getting Started
PHPStan requires PHP >= 7.2. You have to run it in environment with PHP 7.x but the actual code does not have to use PHP 7.x features. (Code written for PHP 5.6 and earlier can run on 7.x mostly unmodified.)
PHPStan works best with modern object-oriented code. The more strongly-typed your code is, the more information you give PHPStan to work with.
Properly annotated and typehinted code (class properties, function and method arguments, return types) helps not only static analysis tools but also other people that work with the code to understand it.
Installation
To start performing analysis on your code, require PHPStan in Composer:
composer require --dev phpstan/phpstan
Composer will install PHPStanβs executable in its bin-dir
which defaults to vendor/bin
.
You can also download the latest PHAR and just use that. But without Composer, you wonβt be able to install and use PHPStan extensions.
All the documentation lives on the phpstan.org website:
A static analysis tool for finding errors in PHP applications.
To get started, check out the installation guide.
You can play around with Psalm on its website.
Documentation is available on Psalmβs website, generated from the docs folder.
Have a look at CONTRIBUTING.md.
Thank you for following this article.
PHPLoc Lines of code static analysis to find PHP code smells
1662017160
Remix and NextJS are good alternatives.
Where is react-static 8? The state of react-static -- and its inevitable death. #1661
You are viewing the docs for v7 of React Static. You can browse all historical versions via Github branches!
React Static
A progressive static-site generator for React.
React-Static is a fast, lightweight, and powerful progressive static site generator based on React and its ecosystem. It resembles the simplicity and developer experience you're used to in tools like Create React App and has been carefully designed for performance, flexibility, and user/developer experience.
See a list of sites
$ npm i -g react-static
# or
$ yarn global add react-static
$ react-static create
$ react-static --help
The CHANGELOG contains information on breaking change for each major version. The latest breaking changes along with their migration tips are located here
A progressive static site is a website where every statically exported HTML page is an entry point to a fully-featured automatically-code-split React application. Just like a normal static site, static progressive websites are capable of loading initial landing pages very quickly, but then extend the user experience by transforming invisibly into a single-page React application.
Once a progressive static site page has loaded its React application it can then do amazing things!
How does it work?
React Static gathers your data, and templates together and intelligently splits them into bite-size static files using webpack and javascript. Once these files have been generated, React Static uses them to render and export a list of routes that you provide it into HTML files! After your site has been exported, the resulting data, template, and html files can be transfered to a static file server and browsed as an awesomely fast and performant static website!
But remember, a progressive static site is more than that...
Little did you know that when React Static exported your site, it also generated a tiny, optimized, and code-split version of your original React application for every page of your site! After these pages have loaded, React invisibly mounts this application to the existing HTML on the page and... πππ You are now using the single page React application you originally built! This application is special, though! While you browse your website, pages that you might go to next are automatically preloaded, making navigation to them instantaneous!.
That's just the beginning! With React Static, you can unleash your creativity and build anything you can imagine with speed and productivity. It even has awesome plugins that will help you on your journey!
React Static is also a great replacement for the ever popular Create React App CLI. It provides a similar developer experience, zero-config environment, and features, but without boxing you in. If you ever need to customize your build system in React Static, there is no need to eject! You can use existing plugins or write your own to customize anything you'd like about the build system. Not building a static site? No worries there, React Static works as an SPA too, even if there is only a single index.html
file.
Need some help? Have a quick question? Click here to go to GitHub Discussions! We are constantly answering questions, discussing features and helping each other out!
We are always looking for people to help us grow react-static
's capabilities and examples. If you have found a bug, or have a feature request let us know! Please follow CONTRIBUTING.md if you want to help out.
Author: React-static
Source Code: https://github.com/react-static/react-static
License: MIT license
1657357200
CoreUI is meant to be the UX game changer. Pure & transparent code is devoid of redundant components, so the app is light enough to offer ultimate user experience. This means mobile devices also, where the navigation is just as easy and intuitive as on a desktop or laptop. The CoreUI Layout API lets you customize your project for almost any device β be it Mobile, Web or WebApp β CoreUI covers them all!
Only customers with Enterpise Membership Plan have access to private github CoreUI Pro repository.
# clone the repo
$ git clone https://github.com/coreui/coreui-free-react-admin-template.git my-project
# go into app's directory
$ cd my-project
# checkout stable version
$ git checkout master
# install app's dependencies
$ npm install
Copy all your files to your project folder and then,
# go into app's directory
$ cd my-project
# install app's dependencies
$ npm install
This project was bootstrapped with Create React App
see also: CRA docs
# dev server with hot reload at http://localhost:3000
$ npm start
Navigate to http://localhost:3000. The app will automatically reload if you change any of the source files.
Run build
to build the project. The build artifacts will be stored in the build/
directory.
# build for production with minification
$ npm run build
Within the download you'll find the following directories and files, logically grouping common assets and providing both compiled and minified variations. You'll see something like this:
CoreUI-React#v3.0.0
βββ public/ #static files
β βββ index.html #html template
β
βββ src/ #project root
β βββ assets/ #assets - js icons object
β βββ containers/ #container source - template layout
| β βββ _nav.js #sidebar config
| β βββ ...
β βββ scss/ #user scss/css source
β βββ views/ #views source
β βββ App.js
β βββ App.test.js
β βββ polyfill.js
β βββ index.js
β βββ routes.js #routes config
β βββ store.js #template state example
β
βββ package.json
The documentation for the CoreUI Admin Template is hosted at our website CoreUI for React
For transparency into our release cycle and in striving to maintain backward compatibility, CoreUI Free Admin Template is maintained under the Semantic Versioning guidelines.
See the Releases section of our project for changelogs for each release version.
Εukasz Holeczek
CoreUI team
Get updates on CoreUI's development and chat with the project maintainers and community members.
copyright 2020 creativeLabs Εukasz Holeczek.
Code released under the MIT license. There is only one limitation you can't canβt re-distribute the CoreUI as stock. You canβt do this if you modify the CoreUI. In past we faced some problems with persons who tried to sell CoreUI based templates.
CoreUI is an MIT licensed open source project and completely free to use. However, the amount of effort needed to maintain and develop new features for the project is not sustainable without proper financial backing. You can support development by buying CoreUI Pro Version.
We're also open to conversations regarding custom sponsorship / consulting arrangements. Get in touch on Twitter.
Author: coreui
Source code: https://github.com/coreui/coreui-free-react-admin-template
License: MIT license
#Bootstrap #React #javascript
1656889860
Deploy functionality is in active development, it soon will be available
First, add Serverless Static to your project, be sure that you already have the serverless-offline plugin already installed
$ npm install serverless-static --save-dev
or, if serverless-offline is not already installed
$ npm install serverless-static serverless-offline --save-dev
Then inside your project's serverless.yml file add following entry to the plugins section: serverless-static. If there is no plugin section you will need to add it to the file.
It should look something like this:
plugins:
- serverless-offline
- serverless-static
custom:
static:
path: ./public # select the folder you want to serve
port: 8000 # select a specific port
# this will overide default behavior
# it will serve the folder ./public
# it will serve it throught localhost:8000
Author: iliasbhal
Source Code: https://github.com/iliasbhal/serverless-static
License:
1656882420
A serverless framework plugin to serve static files locally
Requires Node 10.
It's recommended to use this plugin along with serverless-offline.
Obviously, you should have Serverless-framework installed. If it's not, please start from this guide.
Then install the package:
npm install serverless-plugin-static -D
You can start serving the static folder by the CLI command, but probably for local development you should use serverless-offline plugin:
npm install serverless-offline -D
Add the plugins to your serverless.yml:
plugins:
- serverless-plugin-static
- serverless-offline
Configure the plugin by providing folder path and server port, default values are:
custom:
static:
folder: ./static
port: 8080
Start the application:
serverless offline start
You can also start serving files separately by the command:
serverless serve --folder ./static --port 8080
Or with the shortcuts:
serverless serve -f ./static -p 8080
Note: do not use CLI options with serverless-offline start
command or any other plugins that create a server, since port
argument will cause conflicts.
Author: Sashkopavlenko
Source Code: https://github.com/sashkopavlenko/serverless-plugin-static
License: MIT license
1605177550
#hugo #static #site #generator #markup #static site generator
1597147080
NuxtJS Static Pages and Content API is finally here! NuxtJS just released a brand new version full of awesome features for building static pages, working with content like Markdown files, and lots more. Debbie OβBrien, Head of Learning at NuxtJS, joins me to get hands-on with the latest and greatest features in NuxtJS
#api #nuxtjs #static #content api #features