Giter Club home page Giter Club logo

coding-style-generator's Introduction

Coding Style Generator

Generate a coding style based on your PHP Insights configuration file.

composer require worksome/phpinsights-coding-style-generator

Usage

in the composer bin folder a file named codingStyleGenerator will be available.
The first argument of the tool is the output directory.

This file takes the following parameters:

  • --config-path: Path to the phpinsights configuration file.
  • --insight-config-path: Path to coding style configuration file.

An example command running the tool:

codingStyleGenerator docs --config-path=config/insights.php --insight-config-path=config/codingStyle.php

The tool will generate a folder with a VuePress installation.
In here there will be some files which are overridden each time the coding style is generated.

To render the vuepress installation simply do the following:

# install
yarn global add vuepress
# OR npm install -g vuepress

# start writing
vuepress dev

# build to static files
vuepress build

Configuration

The configuration file is split up in groups, sub-groups and insights.
An example group would be Generic PHP or Laravel, a sub-group would be Functions or Code.
Insights are the insights which are used by php insights.

return [
    'groups' => [
        Group::GENERIC_PHP => [
            'groups' => [
                SubGroup::CODE => [
                    'insights' => [
                        \ObjectCalisthenics\Sniffs\ControlStructures\NoElseSniff::class => [
                            Property::TITLE => 'Avoid else',
                            Property::DESCRIPTION => <<<DESC
                            Else statements adds confusion and often does not contribute to more readable code.  
                            It is recommended to avoid else statements. Usage of early returns can often replace else statements,
                            which also in return will result with the happy path being last.
                            DESC,
                            Property::BAD_CODE => /** @lang PHP */ <<<BAD_CODE
                            if(\$state === 'approved') {
                                return "Happy life";
                            }
                            else {
                                return "bad state";
                            }
                            BAD_CODE,
                            Property::GOOD_CODE => /** @lang PHP */ <<<GOOD_CODE
                            if (\$state !== 'approved') {
                                return "bad state";
                            }
                            
                            return "Happy life";
                            GOOD_CODE,
                        ],
                    ],
                ],
            ],
        ],
        Group::LARAVEL => [
            'groups' => [
                'Controllers' => [
                    'insights' => [
                        'Prefer array parameters when using view' => [
                            Property::ALWAYS_SHOW => true,
                            Property::DESCRIPTION => <<<DESC
                            When passing data to a blade file, it is done with the `view` method.  
                            In the case of passing data, always use the array syntax.
                            DESC,
                            Property::BAD_CODE => /** @lang PHP */ <<<BAD_CODE
                            \$value = 'My value';
                            
                            return view('view', compact('value'));
                            BAD_CODE,
                            Property::GOOD_CODE => /** @lang PHP */ <<<GOOD_CODE
                            return view('view', ['value' => 'My value']);
                            GOOD_CODE,
                        ],
                    ],
                ],
            ],
        ],
    ],
];

coding-style-generator's People

Contributors

olivernybroe avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

coding-style-generator's Issues

Add missing insights to config file

Right now a bunch of insights are not registered in the configuration file.

This means we cannot see them in the generated document.
A list of all missing insights will be added here, and then checked off when they have been added to the configuration.

  • ObjectCalisthenics\Sniffs\Classes\ForbiddenPublicPropertySniff
  • SlevomatCodingStandard\Sniffs\Classes\UnusedPrivateElementsSniff
  • NunoMaduro\PhpInsights\Domain\Sniffs\ForbiddenSetterSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\UnnecessaryFinalModifierSniff
  • PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\PropertyDeclarationSniff
  • SlevomatCodingStandard\Sniffs\Classes\ClassConstantVisibilitySniff
  • SlevomatCodingStandard\Sniffs\Classes\DisallowLateStaticBindingForConstantsSniff
  • SlevomatCodingStandard\Sniffs\Classes\ModernClassNameReferenceSniff
  • SlevomatCodingStandard\Sniffs\Classes\UselessLateStaticBindingSniff
  • PhpCsFixer\Fixer\ClassNotation\VisibilityRequiredFixer (for methods)
  • PhpCsFixer\Fixer\ClassNotation\VisibilityRequiredFixer (for properties)
  • PhpCsFixer\Fixer\ClassNotation\ProtectedToPrivateFixer
  • SlevomatCodingStandard\Sniffs\Variables\UnusedVariableSniff
  • PHP_CodeSniffer\Standards\Zend\Sniffs\Debug\CodeAnalyzerSniff
  • PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\SwitchDeclarationSniff
  • PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\LanguageConstructSpacingSniff
  • ObjectCalisthenics\Sniffs\NamingConventions\ElementNameMinimalLengthSniff
  • ObjectCalisthenics\Sniffs\Metrics\MaxNestingLevelSniff
  • SlevomatCodingStandard\Sniffs\Variables\UselessVariableSniff
  • PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\EvalSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays\ArrayIndentSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\EmptyPHPStatementSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\EmptyStatementSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\ForLoopShouldBeWhileLoopSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\ForLoopWithTestFunctionCallSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\JumbledIncrementerSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\UnconditionalIfStatementSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\UselessOverridingMethodSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\ControlStructures\InlineControlStructureSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\DisallowMultipleStatementsSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\BacktickOperatorSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DiscourageGotoSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\NoSilencedErrorsSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Strings\UnnecessaryStringConcatSniff
  • PHP_CodeSniffer\Standards\PSR12\Sniffs\Keywords\ShortFormTypeKeywordsSniff
  • SlevomatCodingStandard\Sniffs\Arrays\DisallowImplicitArrayCreationSniff
  • SlevomatCodingStandard\Sniffs\ControlStructures\AssignmentInConditionSniff
  • SlevomatCodingStandard\Sniffs\ControlStructures\DisallowContinueWithoutIntegerOperandInSwitchSniff
  • SlevomatCodingStandard\Sniffs\ControlStructures\DisallowEmptySniff
  • SlevomatCodingStandard\Sniffs\ControlStructures\DisallowShortTernaryOperatorSniff
  • SlevomatCodingStandard\Sniffs\ControlStructures\DisallowYodaComparisonSniff
  • SlevomatCodingStandard\Sniffs\ControlStructures\LanguageConstructWithParenthesesSniff
  • SlevomatCodingStandard\Sniffs\Exceptions\DeadCatchSniff
  • SlevomatCodingStandard\Sniffs\Functions\UnusedInheritedVariablePassedToClosureSniff
  • SlevomatCodingStandard\Sniffs\Functions\UselessParameterDefaultValueSniff
  • SlevomatCodingStandard\Sniffs\Namespaces\UseFromSameNamespaceSniff
  • SlevomatCodingStandard\Sniffs\Namespaces\UselessAliasSniff
  • SlevomatCodingStandard\Sniffs\Operators\DisallowEqualOperatorsSniff
  • SlevomatCodingStandard\Sniffs\Operators\RequireCombinedAssignmentOperatorSniff
  • SlevomatCodingStandard\Sniffs\Operators\RequireOnlyStandaloneIncrementAndDecrementOperatorsSniff
  • SlevomatCodingStandard\Sniffs\PHP\OptimizedFunctionsWithoutUnpackingSniff
  • SlevomatCodingStandard\Sniffs\PHP\TypeCastSniff
  • SlevomatCodingStandard\Sniffs\PHP\UselessParenthesesSniff
  • SlevomatCodingStandard\Sniffs\PHP\UselessSemicolonSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\DeclareStrictTypesSniff
  • SlevomatCodingStandard\Sniffs\Variables\DuplicateAssignmentToVariableSniff
  • PhpCsFixer\Fixer\Operator\TernaryToNullCoalescingFixer
  • PhpCsFixer\Fixer\FunctionNotation\CombineNestedDirnameFixer
  • PhpCsFixer\Fixer\LanguageConstruct\DeclareEqualNormalizeFixer
  • PhpCsFixer\Fixer\StringNotation\ExplicitStringVariableFixer
  • PhpCsFixer\Fixer\Operator\NewWithBracesFixer
  • PhpCsFixer\Fixer\ControlStructure\NoAlternativeSyntaxFixer
  • PhpCsFixer\Fixer\Alias\NoMixedEchoPrintFixer
  • PhpCsFixer\Fixer\ArrayNotation\NoMultilineWhitespaceAroundDoubleArrowFixer
  • PhpCsFixer\Fixer\CastNotation\NoShortBoolCastFixer
  • PhpCsFixer\Fixer\ControlStructure\NoSuperfluousElseifFixer
  • PhpCsFixer\Fixer\ControlStructure\NoUnneededControlParenthesesFixer
  • PhpCsFixer\Fixer\ControlStructure\NoUselessElseFixer
  • PhpCsFixer\Fixer\ArrayNotation\NormalizeIndexBraceFixer
  • PhpCsFixer\Fixer\Operator\ObjectOperatorWithoutWhitespaceFixer
  • PhpCsFixer\Fixer\CastNotation\ShortScalarCastFixer
  • PhpCsFixer\Fixer\Operator\TernaryOperatorSpacesFixer
  • SlevomatCodingStandard\Sniffs\TypeHints\NullableTypeForNullDefaultValueSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting\FixmeSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting\TodoSniff
  • SlevomatCodingStandard\Sniffs\Commenting\ForbiddenCommentsSniff
  • SlevomatCodingStandard\Sniffs\Commenting\InlineDocCommentDeclarationSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\DisallowArrayTypeHintSyntaxSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\DisallowMixedTypeHintSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\LongTypeHintsSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\NullTypeHintOnLastPositionSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\ParameterTypeHintSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\PropertyTypeHintSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\ReturnTypeHintSniff
  • SlevomatCodingStandard\Sniffs\Commenting\UselessFunctionDocCommentSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\UselessConstantTypeHintSniff
  • SlevomatCodingStandard\Sniffs\Commenting\UselessInheritDocCommentSniff
  • PhpCsFixer\Fixer\ControlStructure\NoBreakCommentFixer
  • PhpCsFixer\Fixer\Comment\MultilineCommentOpeningClosingFixer
  • PhpCsFixer\Fixer\Comment\NoEmptyCommentFixer
  • PhpCsFixer\Fixer\Phpdoc\PhpdocScalarFixer
  • SlevomatCodingStandard\Sniffs\Functions\UnusedParameterSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\CallTimePassByReferenceSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DeprecatedFunctionsSniff
  • PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions\NullableTypeDeclarationSniff
  • SlevomatCodingStandard\Sniffs\Functions\StaticClosureSniff
  • NunoMaduro\PhpInsights\Domain\Insights\ForbiddenDefineFunctions
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\ForbiddenFunctionsSniff
  • PhpCsFixer\Fixer\FunctionNotation\NoSpacesAfterFunctionNameFixer
  • PhpCsFixer\Fixer\ReturnNotation\ReturnAssignmentFixer
  • PhpCsFixer\Fixer\FunctionNotation\VoidReturnFixer
  • PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\GlobalKeywordSniff
  • NunoMaduro\PhpInsights\Domain\Insights\ForbiddenGlobals
  • NunoMaduro\PhpInsights\Domain\Insights\CyclomaticComplexityIsHigh
  • PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\ValidClassNameSniff
  • PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes\ClassDeclarationSniff
  • ObjectCalisthenics\Sniffs\Files\ClassTraitAndInterfaceLengthSniff
  • ObjectCalisthenics\Sniffs\Metrics\MethodPerClassLimitSniff
  • ObjectCalisthenics\Sniffs\Metrics\PropertyPerClassLimitSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Files\OneClassPerFileSniff
  • SlevomatCodingStandard\Sniffs\Classes\SuperfluousInterfaceNamingSniff
  • SlevomatCodingStandard\Sniffs\Classes\SuperfluousAbstractClassNamingSniff
  • NunoMaduro\PhpInsights\Domain\Insights\ForbiddenDefineGlobalConstants
  • SlevomatCodingStandard\Sniffs\Classes\SuperfluousExceptionNamingSniff
  • ObjectCalisthenics\Sniffs\Files\FunctionLengthSniff
  • PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Files\OneInterfacePerFileSniff
  • SlevomatCodingStandard\Sniffs\Namespaces\NamespaceDeclarationSniff
  • PHP_CodeSniffer\Standards\PSR12\Sniffs\Namespaces\CompoundNamespaceDepthSniff
  • NunoMaduro\PhpInsights\Domain\Insights\ForbiddenTraits
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Files\OneTraitPerFileSniff
  • SlevomatCodingStandard\Sniffs\Classes\SuperfluousTraitNamingSniff
  • PHP_CodeSniffer\Standards\PSR2\Sniffs\Files\ClosingTagSniff
  • PHP_CodeSniffer\Standards\PSR2\Sniffs\Files\EndFileNewlineSniff
  • PHP_CodeSniffer\Standards\PSR1\Sniffs\Files\SideEffectsSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\VersionControl\GitMergeConflictSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Files\ByteOrderMarkSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineEndingsSniff
  • PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\FunctionClosingBraceSniff
  • PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace\ObjectOperatorIndentSniff
  • PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace\ScopeClosingBraceSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays\DisallowLongArraySyntaxSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterCastSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\FunctionCallArgumentSpacingSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\CharacterBeforePHPOpeningTagSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowAlternativePHPTagsSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowShortOpenTagSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseConstantSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseKeywordSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseTypeSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\SAPIUsageSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\SyntaxSniff
  • SlevomatCodingStandard\Sniffs\Arrays\TrailingArrayCommaSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\ArbitraryParenthesesSpacingSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\DisallowTabIndentSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\IncrementDecrementSpacingSniff
  • PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff
  • PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\ElseIfDeclarationSniff
  • PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\UpperCaseConstantNameSniff
  • SlevomatCodingStandard\Sniffs\Namespaces\AlphabeticallySortedUsesSniff
  • SlevomatCodingStandard\Sniffs\Namespaces\NamespaceSpacingSniff
  • SlevomatCodingStandard\Sniffs\Namespaces\RequireOneNamespaceInFileSniff
  • SlevomatCodingStandard\Sniffs\Namespaces\UnusedUsesSniff
  • SlevomatCodingStandard\Sniffs\Namespaces\UseDoesNotStartWithBackslashSniff
  • SlevomatCodingStandard\Sniffs\Namespaces\UseSpacingSniff
  • SlevomatCodingStandard\Sniffs\Operators\SpreadOperatorSpacingSniff
  • SlevomatCodingStandard\Sniffs\PHP\ShortListSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\ParameterTypeHintSpacingSniff
  • SlevomatCodingStandard\Sniffs\TypeHints\ReturnTypeHintSpacingSniff
  • PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\SuperfluousWhitespaceSniff
  • SlevomatCodingStandard\Sniffs\Commenting\DocCommentSpacingSniff
  • PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes\ClassInstantiationSniff
  • PhpCsFixer\Fixer\Basic\BracesFixer
  • PhpCsFixer\Fixer\ClassNotation\ClassDefinitionFixer
  • PhpCsFixer\Fixer\Basic\EncodingFixer
  • PhpCsFixer\Fixer\PhpTag\FullOpeningTagFixer
  • PhpCsFixer\Fixer\FunctionNotation\FunctionDeclarationFixer
  • PhpCsFixer\Fixer\Whitespace\NoSpacesInsideParenthesisFixer
  • PhpCsFixer\Fixer\Whitespace\NoTrailingWhitespaceFixer
  • PhpCsFixer\Fixer\Comment\NoTrailingWhitespaceInCommentFixer
  • PhpCsFixer\Fixer\Whitespace\SingleBlankLineAtEofFixer
  • PhpCsFixer\Fixer\ControlStructure\SwitchCaseSemicolonToColonFixer
  • PhpCsFixer\Fixer\ControlStructure\SwitchCaseSpaceFixer
  • PhpCsFixer\Fixer\Phpdoc\AlignMultilineCommentFixer
  • PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer
  • PhpCsFixer\Fixer\CastNotation\CastSpacesFixer
  • PhpCsFixer\Fixer\FunctionNotation\FunctionTypehintSpaceFixer
  • PhpCsFixer\Fixer\Casing\LowercaseStaticReferenceFixer
  • PhpCsFixer\Fixer\Casing\MagicConstantCasingFixer
  • PhpCsFixer\Fixer\Casing\MagicMethodCasingFixer
  • PhpCsFixer\Fixer\Whitespace\MethodChainingIndentationFixer
  • PhpCsFixer\Fixer\Casing\NativeFunctionCasingFixer
  • PhpCsFixer\Fixer\Casing\NativeFunctionTypeDeclarationCasingFixer
  • PhpCsFixer\Fixer\ClassNotation\NoBlankLinesAfterClassOpeningFixer
  • PhpCsFixer\Fixer\Whitespace\NoExtraBlankLinesFixer
  • PhpCsFixer\Fixer\Semicolon\NoSinglelineWhitespaceBeforeSemicolonsFixer
  • PhpCsFixer\Fixer\Whitespace\NoSpacesAroundOffsetFixer
  • PhpCsFixer\Fixer\ArrayNotation\NoTrailingCommaInSinglelineArrayFixer
  • PhpCsFixer\Fixer\ArrayNotation\NoWhitespaceBeforeCommaInArrayFixer
  • PhpCsFixer\Fixer\Whitespace\NoWhitespaceInBlankLineFixer
  • PhpCsFixer\Fixer\StringNotation\SingleQuoteFixer
  • PhpCsFixer\Fixer\Operator\StandardizeNotEqualsFixer
  • PhpCsFixer\Fixer\Phpdoc\PhpdocIndentFixer
  • PhpCsFixer\Fixer\Phpdoc\PhpdocInlineTagFixer
  • PhpCsFixer\Fixer\Phpdoc\PhpdocTrimFixer
  • PhpCsFixer\Fixer\Import\OrderedImportsFixer
  • PhpCsFixer\Fixer\Phpdoc\PhpdocVarAnnotationCorrectOrderFixer
  • PhpCsFixer\Fixer\ClassNotation\SingleClassElementPerStatementFixer
  • PhpCsFixer\Fixer\Import\SingleImportPerStatementFixer
  • PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.