├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitattributes ├── .gitignore ├── .lintstaged ├── .prettierrc ├── .tslint.json ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── bin ├── docs ├── help.md ├── plugins.md ├── preset.md └── setup.md ├── lerna.json ├── package.json ├── packages ├── cli-utils │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── command.ts │ │ ├── dependencies.ts │ │ ├── files.ts │ │ ├── index.ts │ │ └── preset.ts │ ├── tsconfig.json │ └── tslint.json ├── cli │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── bin │ │ ├── sage │ │ └── sage.cmd │ ├── docs │ ├── package.json │ ├── src │ │ ├── hooks │ │ │ └── telemetry │ │ │ │ └── console.ts │ │ └── index.ts │ ├── test │ │ ├── mocha.opts │ │ └── tsconfig.json │ ├── tsconfig.json │ └── tslint.json ├── preset-bootstrap │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── commands │ │ │ └── preset │ │ │ │ └── bootstrap.ts │ │ └── index.ts │ ├── stubs │ │ ├── scripts │ │ │ ├── app.js │ │ │ ├── customizer.js │ │ │ ├── routes │ │ │ │ ├── about.js │ │ │ │ └── home.js │ │ │ └── utils.js │ │ └── styles │ │ │ ├── app.scss │ │ │ ├── common │ │ │ └── global.scss │ │ │ ├── components │ │ │ ├── buttons.scss │ │ │ ├── comments.scss │ │ │ ├── forms.scss │ │ │ └── wp-classes.scss │ │ │ ├── config │ │ │ ├── external.scss │ │ │ ├── functions.scss │ │ │ └── variables.scss │ │ │ └── layouts │ │ │ ├── footer.scss │ │ │ ├── header.scss │ │ │ ├── pages.scss │ │ │ ├── posts.scss │ │ │ └── tinymce.scss │ ├── test │ │ ├── mocha.opts │ │ └── tsconfig.json │ ├── tsconfig.json │ └── tslint.json ├── preset-none │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── commands │ │ │ └── preset │ │ │ │ └── none.ts │ │ └── index.ts │ ├── stubs │ │ └── styles │ │ │ ├── common │ │ │ └── _variables.scss │ │ │ ├── components │ │ │ ├── _comments.scss │ │ │ ├── _forms.scss │ │ │ └── _wp-classes.scss │ │ │ └── layouts │ │ │ └── _header.scss │ ├── test │ │ ├── mocha.opts │ │ └── tsconfig.json │ ├── tsconfig.json │ └── tslint.json ├── preset │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── commands │ │ │ └── preset │ │ │ │ └── index.ts │ │ └── index.ts │ ├── test │ │ ├── mocha.opts │ │ └── tsconfig.json │ ├── tsconfig.json │ └── tslint.json └── setup │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── src │ ├── commands │ │ └── setup │ │ │ └── index.ts │ ├── index.ts │ └── theme-headers.ts │ ├── test │ ├── mocha.opts │ └── tsconfig.json │ ├── tsconfig.json │ └── tslint.json ├── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | end_of_line = lf 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | packages/*/lib 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "standard", 3 | "env": { 4 | "mocha": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.js text eol=lf 3 | *.ts text eol=lf 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *-debug.log 2 | *-error.log 3 | *.map 4 | .oclif.manifest.json 5 | .nyc_output 6 | coverage 7 | /packages/*/lib 8 | node_modules 9 | package-lock.json 10 | tsconfig.tsbuildinfo 11 | oclif.manifest.json 12 | -------------------------------------------------------------------------------- /.lintstaged: -------------------------------------------------------------------------------- 1 | { 2 | "**/*.ts": [ 3 | "prettier --write", 4 | "git add", 5 | "jest --bail --findRelatedTests" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | printWidth: 120 2 | singleQuote: true 3 | -------------------------------------------------------------------------------- /.tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@oclif/tslint" 3 | } 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [1.0.0-alpha.1](https://github.com/roots/sage-cli/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2019-07-11) 7 | 8 | **Note:** Version bump only for package sage-cli 9 | 10 | 11 | 12 | 13 | 14 | # 1.0.0-alpha.0 (2019-07-11) 15 | 16 | **Note:** Version bump only for package sage-cli 17 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © Roots 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | packages/cli/README.md -------------------------------------------------------------------------------- /bin: -------------------------------------------------------------------------------- 1 | packages/cli/bin -------------------------------------------------------------------------------- /docs/help.md: -------------------------------------------------------------------------------- 1 | `sage help` 2 | =========== 3 | 4 | display help for sage 5 | 6 | * [`sage help [COMMAND]`](#sage-help-command) 7 | 8 | ## `sage help [COMMAND]` 9 | 10 | display help for sage 11 | 12 | ``` 13 | USAGE 14 | $ sage help [COMMAND] 15 | 16 | ARGUMENTS 17 | COMMAND command to show help for 18 | 19 | OPTIONS 20 | --all see all commands in CLI 21 | ``` 22 | 23 | _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v2.2.0/src/commands/help.ts)_ 24 | -------------------------------------------------------------------------------- /docs/plugins.md: -------------------------------------------------------------------------------- 1 | `sage plugins` 2 | ============== 3 | 4 | list installed plugins 5 | 6 | * [`sage plugins`](#sage-plugins) 7 | * [`sage plugins:install PLUGIN...`](#sage-pluginsinstall-plugin) 8 | * [`sage plugins:link PLUGIN`](#sage-pluginslink-plugin) 9 | * [`sage plugins:uninstall PLUGIN...`](#sage-pluginsuninstall-plugin) 10 | * [`sage plugins:update`](#sage-pluginsupdate) 11 | 12 | ## `sage plugins` 13 | 14 | list installed plugins 15 | 16 | ``` 17 | USAGE 18 | $ sage plugins 19 | 20 | OPTIONS 21 | --core show core plugins 22 | 23 | EXAMPLE 24 | $ sage plugins 25 | ``` 26 | 27 | _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v1.7.8/src/commands/plugins/index.ts)_ 28 | 29 | ## `sage plugins:install PLUGIN...` 30 | 31 | installs a plugin into the CLI 32 | 33 | ``` 34 | USAGE 35 | $ sage plugins:install PLUGIN... 36 | 37 | ARGUMENTS 38 | PLUGIN plugin to install 39 | 40 | OPTIONS 41 | -f, --force yarn install with force flag 42 | -h, --help show CLI help 43 | -v, --verbose 44 | 45 | DESCRIPTION 46 | Can be installed from npm or a git url. 47 | 48 | Installation of a user-installed plugin will override a core plugin. 49 | 50 | e.g. If you have a core plugin that has a 'hello' command, installing a user-installed plugin with a 'hello' command 51 | will override the core plugin implementation. This is useful if a user needs to update core plugin functionality in 52 | the CLI without the need to patch and update the whole CLI. 53 | 54 | ALIASES 55 | $ sage plugins:add 56 | 57 | EXAMPLES 58 | $ sage plugins:install myplugin 59 | $ sage plugins:install https://github.com/someuser/someplugin 60 | $ sage plugins:install someuser/someplugin 61 | ``` 62 | 63 | _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v1.7.8/src/commands/plugins/install.ts)_ 64 | 65 | ## `sage plugins:link PLUGIN` 66 | 67 | links a plugin into the CLI for development 68 | 69 | ``` 70 | USAGE 71 | $ sage plugins:link PLUGIN 72 | 73 | ARGUMENTS 74 | PATH [default: .] path to plugin 75 | 76 | OPTIONS 77 | -h, --help show CLI help 78 | -v, --verbose 79 | 80 | DESCRIPTION 81 | Installation of a linked plugin will override a user-installed or core plugin. 82 | 83 | e.g. If you have a user-installed or core plugin that has a 'hello' command, installing a linked plugin with a 'hello' 84 | command will override the user-installed or core plugin implementation. This is useful for development work. 85 | 86 | EXAMPLE 87 | $ sage plugins:link myplugin 88 | ``` 89 | 90 | _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v1.7.8/src/commands/plugins/link.ts)_ 91 | 92 | ## `sage plugins:uninstall PLUGIN...` 93 | 94 | removes a plugin from the CLI 95 | 96 | ``` 97 | USAGE 98 | $ sage plugins:uninstall PLUGIN... 99 | 100 | ARGUMENTS 101 | PLUGIN plugin to uninstall 102 | 103 | OPTIONS 104 | -h, --help show CLI help 105 | -v, --verbose 106 | 107 | ALIASES 108 | $ sage plugins:unlink 109 | $ sage plugins:remove 110 | ``` 111 | 112 | _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v1.7.8/src/commands/plugins/uninstall.ts)_ 113 | 114 | ## `sage plugins:update` 115 | 116 | update installed plugins 117 | 118 | ``` 119 | USAGE 120 | $ sage plugins:update 121 | 122 | OPTIONS 123 | -h, --help show CLI help 124 | -v, --verbose 125 | ``` 126 | 127 | _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v1.7.8/src/commands/plugins/update.ts)_ 128 | -------------------------------------------------------------------------------- /docs/preset.md: -------------------------------------------------------------------------------- 1 | `sage preset` 2 | ============= 3 | 4 | Swap the front-end scaffolding for the theme 5 | 6 | * [`sage preset`](#sage-preset) 7 | * [`sage preset:bootstrap`](#sage-presetbootstrap) 8 | * [`sage preset:none`](#sage-presetnone) 9 | 10 | ## `sage preset` 11 | 12 | Swap the front-end scaffolding for the theme 13 | 14 | ``` 15 | USAGE 16 | $ sage preset 17 | 18 | OPTIONS 19 | -Y, --suppress Suppress warnings when overwriting or deleting files 20 | --clean Uninstall all presets before installing specified preset. 21 | --force Disregard all failsafes. 22 | --no-interaction Do not ask any interactive questions 23 | --path=path Custom path to Sage theme 24 | --uninstall Uninstall specified preset. 25 | 26 | EXAMPLE 27 | $ sage preset:bootstrap 28 | ``` 29 | 30 | _See code: [@sage-cli/plugin-preset](https://github.com/roots/sage-cli/blob/v1.0.0-alpha.1/packages/preset/src/commands/preset/index.ts)_ 31 | 32 | ## `sage preset:bootstrap` 33 | 34 | Use Bootstrap front-end scaffolding. 35 | 36 | ``` 37 | USAGE 38 | $ sage preset:bootstrap 39 | 40 | OPTIONS 41 | -Y, --suppress Suppress warnings when overwriting or deleting files 42 | --clean Uninstall all presets before installing specified preset. 43 | --force Disregard all failsafes. 44 | --no-interaction Do not ask any interactive questions 45 | --path=path Custom path to Sage theme 46 | --uninstall Uninstall specified preset. 47 | 48 | EXAMPLE 49 | $ sage preset:bootstrap 50 | ``` 51 | 52 | _See code: [@sage-cli/plugin-preset-bootstrap](https://github.com/roots/sage-cli/blob/v1.0.0-alpha.1/packages/preset-bootstrap/src/commands/preset/bootstrap.ts)_ 53 | 54 | ## `sage preset:none` 55 | 56 | Vanilla front-end scaffolding. 57 | 58 | ``` 59 | USAGE 60 | $ sage preset:none 61 | 62 | OPTIONS 63 | -Y, --suppress Suppress warnings when overwriting or deleting files 64 | --clean Uninstall all presets before installing specified preset. 65 | --force Disregard all failsafes. 66 | --no-interaction Do not ask any interactive questions 67 | --path=path Custom path to Sage theme 68 | --uninstall Uninstall specified preset. 69 | 70 | ALIASES 71 | $ sage preset:vanilla 72 | 73 | EXAMPLES 74 | $ sage preset:none 75 | $ sage preset:vanilla 76 | ``` 77 | 78 | _See code: [@sage-cli/plugin-preset-none](https://github.com/roots/sage-cli/blob/v1.0.0-alpha.1/packages/preset-none/src/commands/preset/none.ts)_ 79 | -------------------------------------------------------------------------------- /docs/setup.md: -------------------------------------------------------------------------------- 1 | `sage setup` 2 | ============ 3 | 4 | Sets theme headers and other metadata. 5 | 6 | * [`sage setup`](#sage-setup) 7 | 8 | ## `sage setup` 9 | 10 | Sets theme headers and other metadata. 11 | 12 | ``` 13 | USAGE 14 | $ sage setup 15 | 16 | OPTIONS 17 | -Y, --suppress Suppress warnings when overwriting or deleting files 18 | -a, --author=author Author 19 | -d, --description=description Description 20 | -i, --text_domain=text_domain Text Domain 21 | -l, --license=license Theme license 22 | -n, --name=name Theme Name 23 | -p, --template=template Template (parent theme) 24 | -t, --tags=tags Tags (comma separated) 25 | -u, --uri=uri Theme URI 26 | -v, --version=version Theme Version 27 | --author_uri=author_uri Author URI 28 | --banner=banner Banner (appears after the headers) 29 | --force Disregard all failsafes. 30 | --license_uri=license_uri License URI 31 | --no-interaction Do not ask any interactive questions 32 | --path=path Custom path to Sage theme 33 | 34 | EXAMPLE 35 | $ sage setup --name=Sage --version=10.0.0 --uri=https://roots.io/ --description='Sage is a WordPress starter theme' 36 | --author='Roots ' --license='MIT ' 37 | --tags=wordpress,sage,bootstrap 38 | ``` 39 | 40 | _See code: [@sage-cli/plugin-setup](https://github.com/roots/sage-cli/blob/v1.0.0-alpha.1/packages/setup/src/commands/setup/index.ts)_ 41 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-alpha.1", 3 | "npmClient": "yarn", 4 | "useWorkspaces": true, 5 | "command": { 6 | "create": { 7 | "homepage": "https://roots.io/sage/cli", 8 | "license": "MIT" 9 | }, 10 | "publish": { 11 | "allowBranch": "master", 12 | "conventionalCommits": true 13 | }, 14 | "bootstrap": { 15 | "npmClientArgs": [ 16 | "--production", 17 | "--no-optional" 18 | ] 19 | } 20 | }, 21 | "ignoreChanges": [ 22 | "**/__fixtures__/**", 23 | "**/__tests__/**", 24 | "**/*.md" 25 | ], 26 | "packages": [ 27 | "packages/*" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sage-cli-monorepo", 3 | "private": true, 4 | "devDependencies": { 5 | "cross-env": "^6.0", 6 | "eslint": "^6.0", 7 | "eslint-config-standard": "^14.0", 8 | "eslint-plugin-import": "^2.18", 9 | "eslint-plugin-node": "^10.0", 10 | "eslint-plugin-promise": "^4.2", 11 | "eslint-plugin-standard": "^4.0", 12 | "husky": "^3.0", 13 | "lerna": "^3.15", 14 | "rimraf": "^3.0", 15 | "standard": "^14.0", 16 | "ts-node": "^8.3", 17 | "tslint": "^5.18", 18 | "typescript": "^3.4" 19 | }, 20 | "standard": { 21 | "env": "mocha", 22 | "ignore": [ 23 | "**/node_modules/**", 24 | "packages/*/lib/**" 25 | ] 26 | }, 27 | "scripts": { 28 | "clean": "lerna run clean", 29 | "build": "lerna run build", 30 | "postinstall": "lerna exec yarn", 31 | "test": "lerna run test", 32 | "version": "cp packages/cli/CHANGELOG.md CHANGELOG.md && git add CHANGELOG.md", 33 | "posttest": "standard" 34 | }, 35 | "workspaces": [ 36 | "packages/*" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /packages/cli-utils/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [1.0.0-alpha.1](https://github.com/roots/sage-cli/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2019-07-11) 7 | 8 | **Note:** Version bump only for package @sage-cli/cli-utils 9 | 10 | 11 | 12 | 13 | 14 | # 1.0.0-alpha.0 (2019-07-11) 15 | 16 | **Note:** Version bump only for package @sage-cli/cli-utils 17 | -------------------------------------------------------------------------------- /packages/cli-utils/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © Roots 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/cli-utils/README.md: -------------------------------------------------------------------------------- 1 | Sage CLI Utils 2 | ================ 3 | 4 | Base command class and utilities for sage-cli. 5 | 6 | [![Version](https://img.shields.io/npm/v/@sage-cli/cli-utils.svg)](https://npmjs.org/package/@sage-cli/cli-utils) 7 | [![Known Vulnerabilities](https://snyk.io/test/npm/@sage-cli/cli-utils/badge.svg)](https://snyk.io/test/npm/@sage-cli/cli-utils) 8 | [![Downloads/week](https://img.shields.io/npm/dw/@sage-cli/cli-utils.svg)](https://npmjs.org/package/@sage-cli/cli-utils) 9 | [![License](https://img.shields.io/npm/l/@sage-cli/cli-utils.svg)](https://github.com/roots/sage-cli/blob/master/packages/cli-utils/package.json) 10 | -------------------------------------------------------------------------------- /packages/cli-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sage-cli/cli-utils", 3 | "description": "Base command class and utilities for sage-cli.", 4 | "version": "1.0.0-alpha.1", 5 | "author": "QWp6t", 6 | "bugs": "https://github.com/roots/sage-cli/issues", 7 | "engines": { 8 | "node": ">=8.0.0" 9 | }, 10 | "homepage": "https://roots.io/sage/cli", 11 | "keywords": [ 12 | "oclif" 13 | ], 14 | "license": "MIT", 15 | "publishConfig": { 16 | "access": "public" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/roots/sage-cli.git", 21 | "directory": "packages/cli-utils" 22 | }, 23 | "dependencies": { 24 | "@oclif/command": "^1", 25 | "@oclif/parser": "^3", 26 | "chalk": "^3", 27 | "cli-ux": "^5", 28 | "cosmiconfig": "^6", 29 | "fs-extra": "^8", 30 | "klaw-sync": "^6", 31 | "memfs": "^2", 32 | "slugify": "^1", 33 | "tslib": "^1" 34 | }, 35 | "devDependencies": { 36 | "@oclif/dev-cli": "^1", 37 | "@oclif/test": "^1", 38 | "@oclif/tslint": "^3", 39 | "@types/cosmiconfig": "^6", 40 | "@types/fs-extra": "^8", 41 | "@types/klaw-sync": "^6", 42 | "@types/node": "^12", 43 | "rimraf": "^3", 44 | "ts-node": "^8", 45 | "typescript": "^3" 46 | }, 47 | "scripts": { 48 | "clean": "rimraf lib tsconfig.tsbuildinfo *-error.log", 49 | "prebuild": "yarn clean", 50 | "build": "tsc -b", 51 | "lint": "tsc -p test --noEmit && tslint -p test -t stylish", 52 | "prepack": "yarn build", 53 | "test": "mocha --forbid-only \"test/**/*.test.ts\"", 54 | "posttest": "yarn lint", 55 | "preversion": "yarn postpublish", 56 | "postpublish": "rimraf oclif.manifest.json" 57 | }, 58 | "main": "lib/index.js", 59 | "types": "lib/index.d.ts", 60 | "files": [ 61 | "/lib" 62 | ], 63 | "gitHead": "397ccc8faf06049b3d599ee9557956bd0f77a8a4" 64 | } 65 | -------------------------------------------------------------------------------- /packages/cli-utils/src/command.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import { Command as BaseCommand, flags } from '@oclif/command'; 3 | import { cli, IPromptOptions } from 'cli-ux'; 4 | import { Input, args } from '@oclif/parser'; 5 | import cosmiconfig from 'cosmiconfig'; 6 | import * as fs from 'fs-extra'; 7 | import chalk from 'chalk'; 8 | import {Filesystem, files} from './files'; 9 | 10 | const SAGE_PATH_TEST = ['config', 'resources', 'style.css', 'composer.json', 'package.json']; 11 | 12 | export abstract class Command extends BaseCommand { 13 | static flags = { 14 | 'no-interaction': flags.boolean({ description: 'Do not ask any interactive questions', allowNo: false, default: false }), 15 | suppress: flags.boolean({ char: 'Y', description: 'Suppress warnings when overwriting or deleting files', default: false }), 16 | path: flags.string({ description: 'Custom path to Sage theme' }), 17 | force: flags.boolean({ description: 'Disregard all failsafes.' }) 18 | } 19 | 20 | static parent:BaseCommand; 21 | 22 | static args:args.IArg[] = []; 23 | 24 | protected complete?:string = `all done!` 25 | 26 | protected files = files; 27 | 28 | public flags: {[key: string]: any} = {}; 29 | public args: {[key: string]: any} = {}; 30 | 31 | protected interactive?: boolean; 32 | protected suppress?: boolean; 33 | protected telemetry?:{ [key:string]: any }; 34 | protected sage?:cosmiconfig.CosmiconfigResult; 35 | 36 | async init() { 37 | const { args, flags } = this.parse(>this.constructor); 38 | 39 | if (! Command.parent) { 40 | Command.parent = this; 41 | } 42 | 43 | this.args = args; 44 | this.flags = flags; 45 | 46 | this.files.path = flags.path || process.cwd(); 47 | this.interactive = ! flags['no-interaction']; 48 | this.suppress = flags.suppress; 49 | 50 | this.sage = await cosmiconfig('sage').search(this.files.path); 51 | 52 | await this.initialize(); 53 | 54 | if (! this.flags.force) { 55 | await this.failsafe(); 56 | } 57 | } 58 | 59 | async run() { 60 | await this.config.runHook('configure', { 61 | id: this.constructor.name.toLowerCase(), 62 | command: this 63 | }); 64 | await this.configure(); 65 | 66 | await this.config.runHook('validate', { 67 | id: this.constructor.name.toLowerCase(), 68 | command: this 69 | }); 70 | await this.validate(); 71 | 72 | await this.config.runHook('execute', { 73 | id: this.constructor.name.toLowerCase(), 74 | command: this 75 | }); 76 | await this.execute(); 77 | 78 | if (Command.parent !== this) { 79 | return; 80 | } 81 | 82 | await this.config.runHook('filesystem', { 83 | id: this.constructor.name.toLowerCase(), 84 | write: this.files.memory.toJSON(), 85 | delete: this.files.delete_queue, 86 | }); 87 | await this.deleteFiles(); 88 | await this.writeFiles(); 89 | 90 | this.files.clear(); 91 | 92 | if (this.telemetry) { 93 | await this.config.runHook('telemetry', { 94 | id: this.constructor.name.toLowerCase(), 95 | ...this.telemetry, 96 | }); 97 | } 98 | 99 | if (this.complete) { 100 | await this.success(this.complete); 101 | } 102 | } 103 | 104 | async initialize():Promise { 105 | // ... 106 | } 107 | 108 | async failsafe():Promise { 109 | if (! this.sage && SAGE_PATH_TEST.filter(file => fs.existsSync(path.join(this.files.path, file))).length !== SAGE_PATH_TEST.length) { 110 | this.error(`${this.files.path} does not appear to be a valid Sage directory.`, { code: 'InvalidSageDirectory', exit: false }); 111 | this.log(' Try passing `--path=` or `--force` to ignore this error and treat this path a Sage directory.'); 112 | process.exit(1000); 113 | } 114 | } 115 | 116 | async configure():Promise { 117 | // ... 118 | } 119 | 120 | async validate():Promise { 121 | // ... 122 | } 123 | 124 | async execute():Promise { 125 | this.info('This command does nothing.'); 126 | } 127 | 128 | async deleteFiles() : Promise { 129 | const delete_queue = this.files.delete_queue.filter(fs.existsSync); 130 | const confirm = ! delete_queue.length || this.suppress || await this.confirm( 131 | chalk`{yellow.keyword('orange') warning:} This will delete the following files/folders:\n- ${ 132 | this.files.delete_queue 133 | .map(this.files.relative.bind(this.files)) 134 | .join("\n- ") 135 | }\nIs that okay? {yellow [y/n]}` 136 | ); 137 | 138 | if (! confirm) { 139 | this.info('No files were removed.'); 140 | return; 141 | } 142 | 143 | this.files.delete_queue.map(fs.removeSync); 144 | } 145 | 146 | async writeFiles():Promise { 147 | const all_files = this.files.file_list; 148 | const overwrite_list = all_files 149 | .map(this.files.absolute.bind(this.files)) 150 | .filter(this.files.exists.bind(this.files)); 151 | 152 | const overwrite = !overwrite_list.length || this.suppress || await this.confirm( 153 | chalk`{yellow.keyword('orange') warning:} This will overwrite the following files:\n- ${ 154 | overwrite_list 155 | .map(this.files.relative.bind(this.files)) 156 | .join("\n- ") 157 | }\nIs that okay? {yellow [y/n]}` 158 | ); 159 | 160 | if (! overwrite) { 161 | this.info('No files were written.'); 162 | return; 163 | } 164 | 165 | all_files.forEach(source => { 166 | const dest = path.join(this.files.path, this.files.relative(source)); 167 | const dir = path.dirname(dest); 168 | 169 | if (! fs.existsSync(dir)) { 170 | fs.mkdirpSync(dir); 171 | } 172 | 173 | this.files.memory.createReadStream(source) 174 | .pipe(this.files.persistant.createWriteStream(dest)); 175 | }); 176 | } 177 | 178 | info(message:string) { 179 | this.log(chalk`{cyan info:} ${message}`); 180 | } 181 | 182 | warn(message:string|Error) { 183 | super.warn(chalk`{yellow.keyword('orange') warning:} ${message.toString()}`); 184 | } 185 | 186 | warning(message:string) { 187 | this.warn(message); 188 | } 189 | 190 | success(message:string) { 191 | this.log(chalk`{green success:} ${message}`); 192 | } 193 | 194 | async prompt(msg: string, def?: string | IPromptOptions, validate: (response: any) => boolean = (_unused: string) => true) : Promise { 195 | const options = (typeof def === 'string' ? { default: def } : def); 196 | 197 | if (! this.interactive) { 198 | return options.default; 199 | } 200 | 201 | const response = await cli.prompt(msg, options); 202 | try { 203 | if (validate(response)) { 204 | return response; 205 | } 206 | } catch {} 207 | 208 | return await this.prompt(msg, def, validate); 209 | } 210 | 211 | async confirm(message:string, def:boolean = false) : Promise { 212 | if (! this.interactive) { 213 | return def; 214 | } 215 | 216 | return await cli.confirm(message); 217 | } 218 | 219 | async exec(command:{ run(args:string[]):PromiseLike }, argv?:string[]) { 220 | return await command.run(this.execBuildArgs().concat(argv as any).filter(Boolean)); 221 | } 222 | 223 | execBuildArgs():string[] { 224 | const args = ['--path', this.files.path]; 225 | if (this.flags.suppress) { 226 | args.push('--suppress'); 227 | } 228 | if (this.flags.confirm) { 229 | args.push('--confirm'); 230 | } 231 | if (! this.interactive) { 232 | args.push('--no-interaction'); 233 | } 234 | if (this.flags.force) { 235 | args.push('--force'); 236 | } 237 | 238 | return args; 239 | } 240 | } 241 | 242 | export default Command; 243 | 244 | -------------------------------------------------------------------------------- /packages/cli-utils/src/dependencies.ts: -------------------------------------------------------------------------------- 1 | import { spawnSync, SpawnSyncReturns } from 'child_process'; 2 | 3 | interface IDependencyManager { 4 | install(dev:boolean) : SpawnSyncReturns; 5 | uninstall() : SpawnSyncReturns; 6 | } 7 | 8 | export class Dependencies { 9 | protected dependencies:string[]; 10 | protected path:string; 11 | 12 | constructor(dependencies:string|string[], path:string = process.cwd()) { 13 | this.dependencies = [].concat(dependencies as any); 14 | this.path = path; 15 | } 16 | 17 | get client() : IDependencyManager { 18 | if (this.isYarn()) { 19 | return new Yarn(this.dependencies, this.path); 20 | } 21 | 22 | return new NPM(this.dependencies, this.path); 23 | } 24 | 25 | protected isYarn() : boolean { 26 | try { 27 | // user could have yarn installed, but not be using it 28 | // this will return false if the user isn't actually using yarn 29 | if (! process.env.npm_execpath || process.env.npm_execpath.indexOf('yarn') === -1) { 30 | return false; 31 | } 32 | // test to be sure yarn can be spawned 33 | spawnSync('command -v yarn >/dev/null'); 34 | return true; 35 | } catch (e) {} 36 | 37 | return false; 38 | } 39 | } 40 | 41 | export class NPM extends Dependencies implements IDependencyManager { 42 | install(dev:boolean = false) { 43 | const args = ['install'].concat(this.dependencies, ['--prefix', this.path, '--production=false', dev ? '--save-dev' : '--save', '-']); 44 | 45 | return spawnSync('npm', args); 46 | } 47 | 48 | uninstall() { 49 | const args = ['uninstall'].concat(this.dependencies, ['--prefix', this.path]); 50 | return spawnSync('npm', args); 51 | } 52 | } 53 | 54 | export class Yarn extends Dependencies implements IDependencyManager { 55 | install(dev:boolean = false) { 56 | const args = ['add'].concat(this.dependencies, ['--cwd', this.path, '--production=false']); 57 | if (dev) { 58 | args.push('--dev') 59 | } 60 | 61 | return spawnSync('yarn', args); 62 | } 63 | 64 | uninstall() { 65 | const args = ['remove'].concat(this.dependencies, ['--cwd', this.path]); 66 | 67 | return spawnSync('yarn', args); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/cli-utils/src/files.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs-extra'; 2 | import walk from 'klaw-sync'; 3 | import { Volume } from 'memfs'; 4 | import * as original_path from 'path'; 5 | import { Dependencies } from './dependencies'; 6 | 7 | export const path = Object.assign({ 8 | contains: (parent:string, child:string) => parent.split(/[\/\\]/g) 9 | .filter(Boolean).every((segment, i) => child.split(/[\/\\]/g).filter(Boolean)[i] === segment) 10 | }, original_path); 11 | 12 | export class Filesystem { 13 | protected _path:string; 14 | protected fs = new Volume; 15 | public delete_queue:string[] = []; 16 | 17 | constructor(path:string = process.cwd()) { 18 | this._path = path; 19 | } 20 | 21 | public get file_list():string[] { 22 | return Object.keys(this.memory.toJSON()); 23 | } 24 | 25 | get path() { 26 | return this._path; 27 | } 28 | 29 | set path(_path:string) { 30 | if (this.memory.existsSync(this._path)) { 31 | this.memory.renameSync(this._path, _path); 32 | } 33 | this._path = _path; 34 | } 35 | 36 | get memory() { 37 | return this.fs; 38 | } 39 | 40 | get persistant() { 41 | return fs; 42 | } 43 | 44 | public clear() { 45 | this.fs = new Volume; 46 | } 47 | 48 | public absolute(_path:string) { 49 | return path.isAbsolute(_path) ? _path : path.join(this.path, _path); 50 | } 51 | 52 | public relative(_path:string) { 53 | return path.relative(this.path, this.absolute(_path)); 54 | } 55 | 56 | public exists(_path:string) { 57 | return this.persistant.existsSync(this.absolute(_path)); 58 | } 59 | 60 | public read(file:string, options?: null) { 61 | return this.persistant.readFileSync(this.absolute(file), options); 62 | } 63 | 64 | public mkdir(path:string, mode?: undefined) { 65 | if (! this.memory.existsSync(path)) { 66 | this.memory.mkdirpSync(path, mode); 67 | } 68 | } 69 | 70 | public copy(source:string, target:string = this.path) { 71 | 72 | const _copy = (file:string) => { 73 | const dest = path.join(target, file); 74 | this.mkdir(path.dirname(dest)); 75 | this.write(dest, this.persistant.readFileSync(path.join(source, file))); 76 | }; 77 | 78 | if (this.persistant.statSync(source).isFile()) { 79 | _copy(source); 80 | return; 81 | } 82 | 83 | walk(source) 84 | .filter(file => file.stats.isFile()) 85 | .map(file => path.relative(source, file.path)) 86 | .forEach(_copy); 87 | } 88 | 89 | public delete(_path:string) { 90 | const file = path.contains(this.path, this.absolute(_path)) ? this.relative(_path) : path.join(this.path, _path); 91 | 92 | if (! path.contains(this.path, this.absolute(file))) { 93 | throw new Error(`Cannot write ${file}. Cannot write files outside of ${this.path}.`); 94 | } 95 | 96 | this.delete_queue.push(this.absolute(file)); 97 | } 98 | 99 | public write(file:string, contents:any, options?:undefined) { 100 | file = path.contains(this.path, this.absolute(file)) ? this.relative(file) : path.join(this.path, file); 101 | 102 | if (! path.contains(this.path, this.absolute(file))) { 103 | throw new Error(`Cannot write ${file}. Cannot write files outside of ${this.path}.`); 104 | } 105 | 106 | this.mkdir(path.dirname(file)); 107 | this.memory.writeFileSync(this.relative(file), contents, options); 108 | } 109 | 110 | public install(dependencies:string|string[], dev:boolean = false) { 111 | return new Dependencies(dependencies, this.path).client.install(dev); 112 | } 113 | 114 | public uninstall(dependencies:string|string[]) { 115 | return new Dependencies(dependencies, this.path).client.uninstall(); 116 | } 117 | } 118 | 119 | export const files = new Filesystem; 120 | 121 | export default files; 122 | -------------------------------------------------------------------------------- /packages/cli-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | import Command from './command'; 2 | import Preset from './preset'; 3 | import files from './files'; 4 | 5 | export = { 6 | default: Command, 7 | Command, Preset, files 8 | } 9 | -------------------------------------------------------------------------------- /packages/cli-utils/src/preset.ts: -------------------------------------------------------------------------------- 1 | import { Command as ConfigCommand } from '@oclif/config/lib/command'; 2 | import { flags } from '@oclif/command'; 3 | import Command from './command'; 4 | 5 | export default abstract class Preset extends Command { 6 | 7 | protected preset?:string; 8 | 9 | protected dependencies?:string[]; 10 | 11 | get presets() : { [key:string]:ConfigCommand.Plugin } { 12 | const presets: { [key:string]:ConfigCommand.Plugin } = {}; 13 | this.config.plugins 14 | .map(plugin => plugin.commands 15 | .filter(command => command.id.substr(0, 7) === 'preset:') 16 | ) 17 | .filter(commands => commands.length) 18 | .reduce((commands, command) => commands.concat(command), []) 19 | .forEach(command => { 20 | presets[command.id] = command; 21 | }); 22 | 23 | return presets; 24 | } 25 | 26 | static flags = { 27 | ...Command.flags, 28 | clean: flags.boolean({ description: 'Uninstall all presets before installing specified preset.' }), 29 | uninstall: flags.boolean({ description: 'Uninstall specified preset.' }) 30 | } 31 | 32 | async clean() { 33 | const presets = Object.keys(this.presets) 34 | .filter(preset => preset !== 'preset:none' && preset !== 'preset:vanilla') 35 | .map(key => this.presets[key]); 36 | 37 | for (let preset of presets) { 38 | await this.exec(preset.load(), ['--uninstall']); 39 | } 40 | } 41 | 42 | async install() { 43 | if (! this.dependencies) { 44 | return; 45 | } 46 | try { 47 | this.files.install(this.dependencies); 48 | } catch (e) { 49 | this.error(e); 50 | } 51 | this.info(`Installed dependencies ${this.dependencies.join(' ')}`); 52 | } 53 | 54 | async uninstall() { 55 | if (! this.dependencies) { 56 | return; 57 | } 58 | try { 59 | this.files.uninstall(this.dependencies); 60 | } catch (e) { 61 | this.error(e); 62 | } 63 | this.info(`Removed dependencies ${this.dependencies.join(' ')}`); 64 | } 65 | 66 | async execute() { 67 | if (this.flags.clean) { 68 | await this.clean(); 69 | } 70 | if (this.flags.uninstall) { 71 | await this.uninstall(); 72 | } 73 | if (! this.flags.uninstall) { 74 | await this.install(); 75 | } 76 | } 77 | 78 | execBuildArgs():string[] { 79 | const args = super.execBuildArgs(); 80 | 81 | if (this.flags.uninstall && ! this.flags.clean) { 82 | args.push('--uninstall'); 83 | } 84 | 85 | return args; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /packages/cli-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/cli-utils/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@oclif/tslint" 3 | } 4 | -------------------------------------------------------------------------------- /packages/cli/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [1.0.0-alpha.1](https://github.com/roots/sage-cli/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2019-07-11) 7 | 8 | **Note:** Version bump only for package sage-cli 9 | 10 | 11 | 12 | 13 | 14 | # 1.0.0-alpha.0 (2019-07-11) 15 | 16 | **Note:** Version bump only for package sage-cli 17 | -------------------------------------------------------------------------------- /packages/cli/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © Roots 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/cli/README.md: -------------------------------------------------------------------------------- 1 | Sage CLI 2 | ================ 3 | 4 | Perform tasks with sage. 5 | 6 | [![Version](https://img.shields.io/npm/v/sage-cli.svg)](https://npmjs.org/package/sage-cli) 7 | [![Known Vulnerabilities](https://snyk.io/test/npm/sage-cli/badge.svg)](https://snyk.io/test/npm/sage-cli) 8 | [![Downloads/week](https://img.shields.io/npm/dw/sage-cli.svg)](https://npmjs.org/package/sage-cli) 9 | [![License](https://img.shields.io/npm/l/sage-cli.svg)](https://github.com/roots/sage-cli/blob/master/LICENSE.md) 10 | 11 | 12 | * [Usage](#usage) 13 | * [Commands](#commands) 14 | * [Command Topics](#command-topics) 15 | 16 | # Usage 17 | 18 | ```sh-session 19 | $ npm install -g sage-cli 20 | $ sage COMMAND 21 | running command... 22 | $ sage (-v|--version|version) 23 | sage-cli/1.0.0-alpha.1 linux-x64 node-v10.15.3 24 | $ sage --help [COMMAND] 25 | USAGE 26 | $ sage COMMAND 27 | ... 28 | ``` 29 | 30 | # Commands 31 | 32 | # Command Topics 33 | 34 | * [`sage help`](docs/help.md) - display help for sage 35 | * [`sage plugins`](docs/plugins.md) - list installed plugins 36 | * [`sage preset`](docs/preset.md) - Swap the front-end scaffolding for the theme 37 | * [`sage setup`](docs/setup.md) - Sets theme headers and other metadata. 38 | 39 | 40 | -------------------------------------------------------------------------------- /packages/cli/bin/sage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // If someone REALLY wants to see the warning, they can 😏 4 | process.env.MEMFS_DONT_WARN = typeof process.env.MEMFS_DONT_WARN === 'undefined' ? '1' : process.env.MEMFS_DONT_WARN; 5 | 6 | require('@oclif/command').run() 7 | .then(require('@oclif/command/flush')) 8 | .catch(require('@oclif/errors/handle')) 9 | -------------------------------------------------------------------------------- /packages/cli/bin/sage.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | node "%~dp0\run" %* 4 | -------------------------------------------------------------------------------- /packages/cli/docs: -------------------------------------------------------------------------------- 1 | ../../docs -------------------------------------------------------------------------------- /packages/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sage-cli", 3 | "description": "Performs post-installation operations for Sage.", 4 | "version": "1.0.0-alpha.1", 5 | "author": "QWp6t", 6 | "bin": { 7 | "sage": "./bin/sage" 8 | }, 9 | "bugs": "https://github.com/roots/sage-cli/issues", 10 | "engines": { 11 | "node": ">=8.0.0" 12 | }, 13 | "homepage": "https://roots.io/sage/cli", 14 | "keywords": [ 15 | "sage", 16 | "sage-cli", 17 | "oclif" 18 | ], 19 | "license": "MIT", 20 | "publishConfig": { 21 | "access": "public" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/roots/sage-cli.git", 26 | "directory": "packages/cli" 27 | }, 28 | "dependencies": { 29 | "@oclif/command": "^1", 30 | "@oclif/config": "^1", 31 | "@oclif/errors": "^1", 32 | "@oclif/plugin-help": "^2", 33 | "@oclif/plugin-plugins": "^1", 34 | "@sage-cli/plugin-preset": "^1.0.0-alpha.1", 35 | "@sage-cli/plugin-preset-bootstrap": "^1.0.0-alpha.1", 36 | "@sage-cli/plugin-preset-none": "^1.0.0-alpha.1", 37 | "@sage-cli/plugin-setup": "^1.0.0-alpha.1", 38 | "tslib": "^1" 39 | }, 40 | "devDependencies": { 41 | "@oclif/dev-cli": "^1", 42 | "@oclif/test": "^1", 43 | "@oclif/tslint": "^3", 44 | "rimraf": "^3", 45 | "ts-node": "^8", 46 | "typescript": "^3" 47 | }, 48 | "scripts": { 49 | "clean": "rimraf oclif.manifest.json lib tsconfig.tsbuildinfo *-error.log", 50 | "prebuild": "yarn clean", 51 | "build": "tsc -b", 52 | "postbuild": "oclif-dev manifest && oclif-dev readme --multi", 53 | "lint": "tsc -p test --noEmit && tslint -p test -t stylish", 54 | "postpublish": "rimraf oclif.manifest.json", 55 | "posttest": "yarn lint", 56 | "prepack": "yarn build", 57 | "preversion": "yarn postpublish", 58 | "test": "mocha --forbid-only \"test/**/*.test.ts\"", 59 | "version": "oclif-dev readme --multi && git add README.md" 60 | }, 61 | "main": "lib/index.js", 62 | "types": "lib/index.d.ts", 63 | "files": [ 64 | "/bin", 65 | "/lib", 66 | "/npm-shrinkwrap.json", 67 | "/oclif.manifest.json" 68 | ], 69 | "oclif": { 70 | "commands": "./lib/commands", 71 | "bin": "sage", 72 | "scope": "sage-cli", 73 | "dirname": "sage", 74 | "plugins": [ 75 | "@oclif/plugin-help", 76 | "@oclif/plugin-plugins", 77 | "@sage-cli/plugin-setup", 78 | "@sage-cli/plugin-preset", 79 | "@sage-cli/plugin-preset-bootstrap", 80 | "@sage-cli/plugin-preset-none" 81 | ], 82 | "hooks": { 83 | "telemetry": [ 84 | "./lib/hooks/telemetry/console" 85 | ] 86 | } 87 | }, 88 | "gitHead": "397ccc8faf06049b3d599ee9557956bd0f77a8a4" 89 | } 90 | -------------------------------------------------------------------------------- /packages/cli/src/hooks/telemetry/console.ts: -------------------------------------------------------------------------------- 1 | /** this shows the user the telemetry data is being collected */ 2 | import { Hook } from '@oclif/config' 3 | 4 | export const log: Hook<'telemetry'> = async function (options) { 5 | delete options.config; 6 | console.log('The following user data has been collected:'); 7 | console.log(JSON.stringify(options, null, 2)); 8 | } 9 | -------------------------------------------------------------------------------- /packages/cli/src/index.ts: -------------------------------------------------------------------------------- 1 | export {run} from '@oclif/command' 2 | -------------------------------------------------------------------------------- /packages/cli/test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require ts-node/register 2 | --watch-extensions ts 3 | --recursive 4 | --reporter spec 5 | --timeout 5000 6 | -------------------------------------------------------------------------------- /packages/cli/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "compilerOptions": { 4 | "noEmit": true 5 | }, 6 | "references": [ 7 | {"path": ".."} 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/cli/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@oclif/tslint" 3 | } 4 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [1.0.0-alpha.1](https://github.com/roots/sage-cli/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2019-07-11) 7 | 8 | 9 | ### Bug Fixes 10 | 11 | * **presets:** include stubs ([bbf96ba](https://github.com/roots/sage-cli/commit/bbf96ba)) 12 | 13 | 14 | 15 | 16 | 17 | # 1.0.0-alpha.0 (2019-07-11) 18 | 19 | **Note:** Version bump only for package @sage-cli/plugin-preset-bootstrap 20 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © Roots 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/README.md: -------------------------------------------------------------------------------- 1 | Preset plugin for [`sage`](https://roots.io/sage/cli) 2 | ================ 3 | 4 | Swap the front-end scaffolding for the theme. 5 | 6 | [![Version](https://img.shields.io/npm/v/@sage-cli/plugin-preset-bootstrap.svg)](https://npmjs.org/package/@sage-cli/plugin-preset-bootstrap) 7 | [![Known Vulnerabilities](https://snyk.io/test/npm/@sage-cli/plugin-preset-bootstrap/badge.svg)](https://snyk.io/test/npm/@sage-cli/plugin-preset-bootstrap) 8 | [![Downloads/week](https://img.shields.io/npm/dw/@sage-cli/plugin-preset-bootstrap.svg)](https://npmjs.org/package/@sage-cli/plugin-preset-bootstrap) 9 | [![License](https://img.shields.io/npm/l/@sage-cli/plugin-preset-bootstrap.svg)](https://github.com/roots/sage-cli/blob/master/packages/preset-bootstrap/package.json) 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ```sh-session 18 | $ npm install -g @sage-cli/plugin-preset-bootstrap 19 | $ sage COMMAND 20 | running command... 21 | $ sage (-v|--version|version) 22 | @sage-cli/plugin-preset-bootstrap/1.0.0-alpha.1 linux-x64 node-v10.15.3 23 | $ sage --help [COMMAND] 24 | USAGE 25 | $ sage COMMAND 26 | ... 27 | ``` 28 | 29 | 30 | 31 | * [`sage preset:bootstrap`](#sage-presetbootstrap) 32 | 33 | ## `sage preset:bootstrap` 34 | 35 | Use Bootstrap front-end scaffolding. 36 | 37 | ``` 38 | USAGE 39 | $ sage preset:bootstrap 40 | 41 | OPTIONS 42 | -Y, --suppress Suppress warnings when overwriting or deleting files 43 | --clean Uninstall all presets before installing specified preset. 44 | --force Disregard all failsafes. 45 | --no-interaction Do not ask any interactive questions 46 | --path=path Custom path to Sage theme 47 | --uninstall Uninstall specified preset. 48 | 49 | EXAMPLE 50 | $ sage preset:bootstrap 51 | ``` 52 | 53 | _See code: [src/commands/preset/bootstrap.ts](https://github.com/roots/sage-cli/blob/v1.0.0-alpha.1/packages/preset-bootstrap/src/commands/preset/bootstrap.ts)_ 54 | 55 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sage-cli/plugin-preset-bootstrap", 3 | "description": "Performs post-installation operations for Sage.", 4 | "version": "1.0.0-alpha.1", 5 | "author": "QWp6t", 6 | "bugs": "https://github.com/roots/sage-cli/issues", 7 | "engines": { 8 | "node": ">=8.0.0" 9 | }, 10 | "homepage": "https://roots.io/sage/docs/cli", 11 | "keywords": [ 12 | "sage", 13 | "sage-cli" 14 | ], 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/roots/sage-cli.git", 22 | "directory": "packages/preset-bootstrap" 23 | }, 24 | "dependencies": { 25 | "@sage-cli/cli-utils": "^1.0.0-alpha.1" 26 | }, 27 | "devDependencies": { 28 | "@oclif/dev-cli": "^1", 29 | "@oclif/test": "^1", 30 | "@oclif/tslint": "^3", 31 | "rimraf": "^3", 32 | "ts-node": "^8", 33 | "typescript": "^3" 34 | }, 35 | "scripts": { 36 | "clean": "rimraf oclif.manifest.json lib tsconfig.tsbuildinfo *-error.log", 37 | "prebuild": "yarn clean", 38 | "build": "tsc -b", 39 | "postbuild": "oclif-dev manifest && oclif-dev readme", 40 | "lint": "tsc -p test --noEmit && tslint -p test -t stylish", 41 | "postpublish": "rimraf oclif.manifest.json", 42 | "posttest": "yarn lint", 43 | "prepack": "yarn build", 44 | "preversion": "yarn postpublish", 45 | "test": "mocha --forbid-only \"test/**/*.test.ts\"", 46 | "version": "oclif-dev readme && git add README.md" 47 | }, 48 | "main": "lib/index.js", 49 | "types": "lib/index.d.ts", 50 | "files": [ 51 | "/lib", 52 | "/stubs", 53 | "/oclif.manifest.json" 54 | ], 55 | "oclif": { 56 | "commands": "./lib/commands", 57 | "bin": "sage", 58 | "devPlugins": [ 59 | "@oclif/plugin-help" 60 | ], 61 | "topics": { 62 | "preset": { 63 | "description": "Swap the front-end scaffolding for the theme" 64 | } 65 | }, 66 | "repositoryPrefix": "<%- repo %>/blob/v<%- version %>/packages/preset-bootstrap/<%- commandPath %>" 67 | }, 68 | "gitHead": "397ccc8faf06049b3d599ee9557956bd0f77a8a4" 69 | } 70 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/src/commands/preset/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import {Preset} from '@sage-cli/cli-utils'; 3 | 4 | const root_path = path.resolve(`${__dirname}/../../../`); 5 | 6 | export default class Bootstrap extends Preset { 7 | static description = 'Use Bootstrap front-end scaffolding.' 8 | 9 | static examples = [ 10 | `$ sage preset:bootstrap`, 11 | ] 12 | 13 | static flags = { 14 | ...Preset.flags, 15 | } 16 | 17 | protected dependencies = ['bootstrap', 'popper.js', 'jquery']; 18 | 19 | protected preset = 'bootstrap'; 20 | 21 | async install() { 22 | await super.install(); 23 | this.files.copy(path.join(root_path, 'stubs'), path.join(this.files.path, 'resources', 'assets')); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/src/index.ts: -------------------------------------------------------------------------------- 1 | export default {} 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/scripts/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * External Dependencies 3 | */ 4 | import 'jquery'; 5 | import 'bootstrap'; 6 | import { router } from 'js-dom-router'; 7 | 8 | /** 9 | * DOM-based routing 10 | */ 11 | import about from './routes/about'; 12 | 13 | /** 14 | * Below is an example of a dynamic import; it will not be loaded until it's needed. 15 | * 16 | * See: {@link https://webpack.js.org/guides/code-splitting/#dynamic-imports | Dynamic Imports} 17 | */ 18 | const home = async () => import(/* webpackChunkName: "scripts/routes/home" */ './routes/home'); 19 | 20 | /** 21 | * Set up DOM router 22 | * 23 | * .on(, callback) 24 | * 25 | * See: {@link http://goo.gl/EUTi53 | Markup-based Unobtrusive Comprehensive DOM-ready Execution} by Paul Irish 26 | */ 27 | router 28 | .on('about-us', about) 29 | .on('home', async (event) => (await home()).default(event)) 30 | .ready(); 31 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/scripts/customizer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file allows you to add functionality to the Theme Customizer 3 | * live preview. jQuery is readily available. 4 | * 5 | * {@link https://codex.wordpress.org/Theme_Customization_API} 6 | */ 7 | 8 | /** 9 | * Change the blog name value. 10 | * 11 | * @param {string} value 12 | */ 13 | wp.customize('blogname', (value) => { 14 | value.bind(to => $('.brand').text(to)); 15 | }); 16 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/scripts/routes/about.js: -------------------------------------------------------------------------------- 1 | /** 2 | * About Us 3 | */ 4 | export default () => { 5 | //-- 6 | }; 7 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/scripts/routes/home.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Home 3 | */ 4 | export default () => { 5 | //-- 6 | }; 7 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/scripts/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Execute a function when the DOM is fully loaded. 3 | * 4 | * @param {function} fn 5 | */ 6 | export const ready = fn => document.readyState !== 'loading' 7 | ? window.setTimeout(fn, 0) 8 | : document.addEventListener('DOMContentLoaded', fn); 9 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/app.scss: -------------------------------------------------------------------------------- 1 | /** Config */ 2 | @import 'config/functions'; 3 | @import 'config/variables'; 4 | @import 'config/external'; 5 | 6 | /** Common */ 7 | @import 'common/global'; 8 | 9 | /** Components */ 10 | @import 'components/buttons'; 11 | @import 'components/comments'; 12 | @import 'components/forms'; 13 | @import 'components/wp-classes'; 14 | 15 | /** Layouts */ 16 | @import 'layouts/header'; 17 | @import 'layouts/footer'; 18 | @import 'layouts/pages'; 19 | @import 'layouts/posts'; 20 | @import 'layouts/tinymce'; 21 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/common/global.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Global 3 | */ 4 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/components/buttons.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Buttons 3 | */ 4 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/components/comments.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Comments 3 | */ 4 | 5 | .comment-list { 6 | @extend .list-unstyled; 7 | 8 | ol { 9 | list-style: none; 10 | } 11 | 12 | p { 13 | @extend .form-group; 14 | } 15 | 16 | input[type='text'], 17 | input[type='email'], 18 | input[type='url'], 19 | textarea { 20 | @extend .form-control; 21 | } 22 | 23 | input[type='submit'] { 24 | @extend .btn; 25 | @extend .btn-secondary; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/components/forms.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Search Form 3 | */ 4 | 5 | .search-form { 6 | @extend .form-inline; 7 | 8 | label { 9 | @extend .form-group; 10 | 11 | font-weight: normal; 12 | } 13 | 14 | .search-field { 15 | @extend .form-control; 16 | } 17 | 18 | .search-submit { 19 | @extend .btn; 20 | @extend .btn-secondary; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/components/wp-classes.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress Generated Classes 3 | * @see http://codex.wordpress.org/CSS#WordPress_Generated_Classes 4 | */ 5 | 6 | /** Media alignment */ 7 | .alignnone { 8 | margin-left: 0; 9 | margin-right: 0; 10 | max-width: 100%; 11 | height: auto; 12 | } 13 | 14 | .aligncenter { 15 | display: block; 16 | margin: ($spacer / 2) auto; 17 | height: auto; 18 | } 19 | 20 | .alignleft, 21 | .alignright { 22 | margin-bottom: ($spacer / 2); 23 | height: auto; 24 | } 25 | 26 | @include media-breakpoint-up(sm) { 27 | .alignleft { 28 | float: left; 29 | margin-right: ($spacer / 2); 30 | } 31 | 32 | .alignright { 33 | float: right; 34 | margin-left: ($spacer / 2); 35 | } 36 | } 37 | 38 | /** Captions */ 39 | .wp-caption { 40 | @extend .figure; 41 | 42 | img { 43 | @extend .figure-img; 44 | @extend .img-fluid; 45 | } 46 | } 47 | 48 | .wp-caption-text { 49 | @extend .figure-caption; 50 | } 51 | 52 | /** Text meant only for screen readers */ 53 | .screen-reader-text { 54 | @extend .sr-only; 55 | @extend .sr-only-focusable; 56 | } 57 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/config/external.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * External 3 | */ 4 | 5 | @import '~bootstrap/scss/bootstrap'; 6 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/config/functions.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Functions 3 | */ 4 | 5 | @import '~bootstrap/scss/functions'; 6 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/config/variables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Variables 3 | */ 4 | 5 | $theme-colors: ( 6 | primary: #525ddc 7 | ); 8 | 9 | /** Bootstrap Navbar Fix (https://git.io/fADqW) */ 10 | $navbar-dark-toggler-icon-bg: none; 11 | $navbar-light-toggler-icon-bg: none; 12 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/layouts/footer.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Footer 3 | */ 4 | 5 | .content-info { 6 | // 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/layouts/header.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Header 3 | */ 4 | 5 | .banner .nav { 6 | li { 7 | @extend .nav-item; 8 | } 9 | 10 | a { 11 | @extend .nav-link; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/layouts/pages.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Pages 3 | */ 4 | 5 | .page { 6 | // 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/layouts/posts.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Posts 3 | */ 4 | 5 | .post { 6 | // 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/stubs/styles/layouts/tinymce.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE 3 | */ 4 | 5 | body#tinymce { 6 | margin: 1rem !important; 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require ts-node/register 2 | --watch-extensions ts 3 | --recursive 4 | --reporter spec 5 | --timeout 5000 6 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "compilerOptions": { 4 | "sourceMap": true, 5 | "noEmit": true 6 | }, 7 | "references": [ 8 | {"path": ".."} 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib" 6 | }, 7 | "exclude": [ 8 | "stubs" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/preset-bootstrap/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@oclif/tslint" 3 | } 4 | -------------------------------------------------------------------------------- /packages/preset-none/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [1.0.0-alpha.1](https://github.com/roots/sage-cli/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2019-07-11) 7 | 8 | 9 | ### Bug Fixes 10 | 11 | * **presets:** include stubs ([bbf96ba](https://github.com/roots/sage-cli/commit/bbf96ba)) 12 | 13 | 14 | 15 | 16 | 17 | # 1.0.0-alpha.0 (2019-07-11) 18 | 19 | **Note:** Version bump only for package @sage-cli/plugin-preset-none 20 | -------------------------------------------------------------------------------- /packages/preset-none/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © Roots 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/preset-none/README.md: -------------------------------------------------------------------------------- 1 | Preset plugin for [`sage`](https://roots.io/sage/cli) 2 | ================ 3 | 4 | Swap the front-end scaffolding for the theme. 5 | 6 | [![Version](https://img.shields.io/npm/v/@sage-cli/plugin-preset-none.svg)](https://npmjs.org/package/@sage-cli/plugin-preset-none) 7 | [![Known Vulnerabilities](https://snyk.io/test/npm/@sage-cli/plugin-preset-none/badge.svg)](https://snyk.io/test/npm/@sage-cli/plugin-preset-none) 8 | [![Downloads/week](https://img.shields.io/npm/dw/@sage-cli/plugin-preset-none.svg)](https://npmjs.org/package/@sage-cli/plugin-preset-none) 9 | [![License](https://img.shields.io/npm/l/@sage-cli/plugin-preset-none.svg)](https://github.com/roots/sage-cli/blob/master/packages/preset-none/package.json) 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ```sh-session 18 | $ npm install -g @sage-cli/plugin-preset-none 19 | $ sage COMMAND 20 | running command... 21 | $ sage (-v|--version|version) 22 | @sage-cli/plugin-preset-none/1.0.0-alpha.1 linux-x64 node-v10.15.3 23 | $ sage --help [COMMAND] 24 | USAGE 25 | $ sage COMMAND 26 | ... 27 | ``` 28 | 29 | 30 | 31 | * [`sage preset:none`](#sage-presetnone) 32 | 33 | ## `sage preset:none` 34 | 35 | Vanilla front-end scaffolding. 36 | 37 | ``` 38 | USAGE 39 | $ sage preset:none 40 | 41 | OPTIONS 42 | -Y, --suppress Suppress warnings when overwriting or deleting files 43 | --clean Uninstall all presets before installing specified preset. 44 | --force Disregard all failsafes. 45 | --no-interaction Do not ask any interactive questions 46 | --path=path Custom path to Sage theme 47 | --uninstall Uninstall specified preset. 48 | 49 | ALIASES 50 | $ sage preset:vanilla 51 | 52 | EXAMPLES 53 | $ sage preset:none 54 | $ sage preset:vanilla 55 | ``` 56 | 57 | _See code: [src/commands/preset/none.ts](https://github.com/roots/sage-cli/blob/v1.0.0-alpha.1/packages/preset-none/src/commands/preset/none.ts)_ 58 | 59 | -------------------------------------------------------------------------------- /packages/preset-none/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sage-cli/plugin-preset-none", 3 | "description": "Performs post-installation operations for Sage.", 4 | "version": "1.0.0-alpha.1", 5 | "author": "QWp6t", 6 | "bugs": "https://github.com/roots/sage-cli/issues", 7 | "engines": { 8 | "node": ">=8.0.0" 9 | }, 10 | "homepage": "https://roots.io/sage/docs/cli", 11 | "keywords": [ 12 | "sage", 13 | "sage-cli" 14 | ], 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/roots/sage-cli.git", 22 | "directory": "packages/preset-none" 23 | }, 24 | "dependencies": { 25 | "@sage-cli/cli-utils": "^1.0.0-alpha.1" 26 | }, 27 | "devDependencies": { 28 | "@oclif/dev-cli": "^1", 29 | "@oclif/test": "^1", 30 | "@oclif/tslint": "^3", 31 | "rimraf": "^3", 32 | "ts-node": "^8", 33 | "typescript": "^3" 34 | }, 35 | "scripts": { 36 | "clean": "rimraf oclif.manifest.json lib tsconfig.tsbuildinfo *-error.log", 37 | "prebuild": "yarn clean", 38 | "build": "tsc -b", 39 | "postbuild": "oclif-dev manifest && oclif-dev readme", 40 | "lint": "tsc -p test --noEmit && tslint -p test -t stylish", 41 | "postpublish": "rimraf oclif.manifest.json", 42 | "posttest": "yarn lint", 43 | "prepack": "yarn build", 44 | "preversion": "yarn postpublish", 45 | "test": "mocha --forbid-only \"test/**/*.test.ts\"", 46 | "version": "oclif-dev readme && git add README.md" 47 | }, 48 | "main": "lib/index.js", 49 | "types": "lib/index.d.ts", 50 | "files": [ 51 | "/lib", 52 | "/stubs", 53 | "/oclif.manifest.json" 54 | ], 55 | "oclif": { 56 | "commands": "./lib/commands", 57 | "bin": "sage", 58 | "devPlugins": [ 59 | "@oclif/plugin-help" 60 | ], 61 | "topics": { 62 | "preset": { 63 | "description": "Swap the front-end scaffolding for the theme" 64 | } 65 | }, 66 | "repositoryPrefix": "<%- repo %>/blob/v<%- version %>/packages/preset-none/<%- commandPath %>" 67 | }, 68 | "gitHead": "397ccc8faf06049b3d599ee9557956bd0f77a8a4" 69 | } 70 | -------------------------------------------------------------------------------- /packages/preset-none/src/commands/preset/none.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import {Preset} from '@sage-cli/cli-utils'; 3 | 4 | const root_path = path.dirname(`${__dirname}/../../../../`); 5 | 6 | export default class Vanilla extends Preset { 7 | static description = 'Vanilla front-end scaffolding.' 8 | 9 | static aliases = ['preset:vanilla'] 10 | 11 | static examples = [ 12 | `$ sage preset:none`, 13 | `$ sage preset:vanilla`, 14 | ] 15 | 16 | static flags = { 17 | ...Preset.flags, 18 | } 19 | 20 | protected preset = 'none'; 21 | 22 | async execute() { 23 | await this.clean(); 24 | this.files.delete(path.join(this.files.path, 'resources', 'assets')); 25 | this.files.copy(path.join(root_path, 'stubs'), path.join(this.files.path, 'resources', 'assets')); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/preset-none/src/index.ts: -------------------------------------------------------------------------------- 1 | export default {} 2 | -------------------------------------------------------------------------------- /packages/preset-none/stubs/styles/common/_variables.scss: -------------------------------------------------------------------------------- 1 | /** Colors */ 2 | $brand-primary: #525ddc; 3 | 4 | /** Box Model */ 5 | $spacer: 2rem; 6 | -------------------------------------------------------------------------------- /packages/preset-none/stubs/styles/components/_comments.scss: -------------------------------------------------------------------------------- 1 | // TODO: .comment-list {} 2 | // TODO: .comment-list ol {} 3 | // TODO: .comment-form p {} 4 | // TODO: .comment-form input {} 5 | // TODO: .comment-form textarea {} 6 | -------------------------------------------------------------------------------- /packages/preset-none/stubs/styles/components/_forms.scss: -------------------------------------------------------------------------------- 1 | /** Search form */ 2 | // TODO: .search-form {} 3 | // TODO: .search-form label {} 4 | // TODO: .search-form .search-field {} 5 | // TODO: .search-form .search-submit {} 6 | -------------------------------------------------------------------------------- /packages/preset-none/stubs/styles/components/_wp-classes.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress Generated Classes 3 | * @see http://codex.wordpress.org/CSS#WordPress_Generated_Classes 4 | */ 5 | 6 | /** Media alignment */ 7 | .alignnone { 8 | margin-left: 0; 9 | margin-right: 0; 10 | max-width: 100%; 11 | height: auto; 12 | } 13 | 14 | .aligncenter { 15 | display: block; 16 | margin: ($spacer / 2) auto; 17 | height: auto; 18 | } 19 | 20 | .alignleft, 21 | .alignright { 22 | margin-bottom: ($spacer / 2); 23 | height: auto; 24 | } 25 | 26 | @media (min-width: 30rem) { 27 | .alignleft { 28 | float: left; 29 | margin-right: ($spacer / 2); 30 | } 31 | 32 | .alignright { 33 | float: right; 34 | margin-left: ($spacer / 2); 35 | } 36 | } 37 | 38 | /** Captions */ 39 | 40 | // TODO: .wp-caption {} 41 | // TODO: .wp-caption img {} 42 | // TODO: .wp-caption-text {} 43 | 44 | /** Text meant only for screen readers */ 45 | .screen-reader-text { 46 | position: absolute; 47 | width: 1px; 48 | height: 1px; 49 | padding: 0; 50 | margin: -1px; 51 | overflow: hidden; 52 | clip: rect(0, 0, 0, 0); 53 | border: 0; 54 | color: #000; 55 | background: #fff; 56 | } 57 | -------------------------------------------------------------------------------- /packages/preset-none/stubs/styles/layouts/_header.scss: -------------------------------------------------------------------------------- 1 | // TODO: .banner .nav li {} 2 | // TODO: .banner .nav a {} 3 | -------------------------------------------------------------------------------- /packages/preset-none/test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require ts-node/register 2 | --watch-extensions ts 3 | --recursive 4 | --reporter spec 5 | --timeout 5000 6 | -------------------------------------------------------------------------------- /packages/preset-none/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "compilerOptions": { 4 | "sourceMap": true, 5 | "noEmit": true 6 | }, 7 | "references": [ 8 | {"path": ".."} 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/preset-none/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib" 6 | }, 7 | "exclude": [ 8 | "stubs" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/preset-none/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@oclif/tslint" 3 | } 4 | -------------------------------------------------------------------------------- /packages/preset/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [1.0.0-alpha.1](https://github.com/roots/sage-cli/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2019-07-11) 7 | 8 | **Note:** Version bump only for package @sage-cli/plugin-preset 9 | 10 | 11 | 12 | 13 | 14 | # 1.0.0-alpha.0 (2019-07-11) 15 | 16 | **Note:** Version bump only for package @sage-cli/plugin-preset 17 | -------------------------------------------------------------------------------- /packages/preset/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © Roots 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/preset/README.md: -------------------------------------------------------------------------------- 1 | Preset plugin for [`sage`](https://roots.io/sage/cli) 2 | ================ 3 | 4 | Swap the front-end scaffolding for the theme. 5 | 6 | [![Version](https://img.shields.io/npm/v/@sage-cli/plugin-preset.svg)](https://npmjs.org/package/@sage-cli/plugin-preset) 7 | [![Known Vulnerabilities](https://snyk.io/test/npm/@sage-cli/plugin-preset/badge.svg)](https://snyk.io/test/npm/@sage-cli/plugin-preset) 8 | [![Downloads/week](https://img.shields.io/npm/dw/@sage-cli/plugin-preset.svg)](https://npmjs.org/package/@sage-cli/plugin-preset) 9 | [![License](https://img.shields.io/npm/l/@sage-cli/plugin-preset.svg)](https://github.com/roots/sage-cli/blob/master/packages/preset/package.json) 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ```sh-session 18 | $ npm install -g @sage-cli/plugin-preset 19 | $ sage COMMAND 20 | running command... 21 | $ sage (-v|--version|version) 22 | @sage-cli/plugin-preset/1.0.0-alpha.1 linux-x64 node-v10.15.3 23 | $ sage --help [COMMAND] 24 | USAGE 25 | $ sage COMMAND 26 | ... 27 | ``` 28 | 29 | 30 | 31 | * [`sage preset`](#sage-preset) 32 | 33 | ## `sage preset` 34 | 35 | Swap the front-end scaffolding for the theme 36 | 37 | ``` 38 | USAGE 39 | $ sage preset 40 | 41 | OPTIONS 42 | -Y, --suppress Suppress warnings when overwriting or deleting files 43 | --clean Uninstall all presets before installing specified preset. 44 | --force Disregard all failsafes. 45 | --no-interaction Do not ask any interactive questions 46 | --path=path Custom path to Sage theme 47 | --uninstall Uninstall specified preset. 48 | 49 | EXAMPLE 50 | $ sage preset:bootstrap 51 | ``` 52 | 53 | _See code: [src/commands/preset/index.ts](https://github.com/roots/sage-cli/blob/v1.0.0-alpha.1/packages/preset/src/commands/preset/index.ts)_ 54 | 55 | -------------------------------------------------------------------------------- /packages/preset/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sage-cli/plugin-preset", 3 | "description": "Swap the front-end scaffolding for the theme", 4 | "version": "1.0.0-alpha.1", 5 | "author": "QWp6t", 6 | "bugs": "https://github.com/roots/sage-cli/issues", 7 | "engines": { 8 | "node": ">=8.0.0" 9 | }, 10 | "homepage": "https://roots.io/sage/docs/cli", 11 | "keywords": [ 12 | "sage", 13 | "sage-cli" 14 | ], 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/roots/sage-cli.git", 22 | "directory": "packages/preset" 23 | }, 24 | "dependencies": { 25 | "@sage-cli/cli-utils": "^1.0.0-alpha.1" 26 | }, 27 | "devDependencies": { 28 | "@oclif/dev-cli": "^1", 29 | "@oclif/test": "^1", 30 | "@oclif/tslint": "^3", 31 | "rimraf": "^3", 32 | "ts-node": "^8", 33 | "typescript": "^3" 34 | }, 35 | "scripts": { 36 | "clean": "rimraf oclif.manifest.json lib tsconfig.tsbuildinfo *-error.log", 37 | "prebuild": "yarn clean", 38 | "build": "tsc -b", 39 | "postbuild": "oclif-dev manifest && oclif-dev readme", 40 | "lint": "tsc -p test --noEmit && tslint -p test -t stylish", 41 | "postpublish": "rimraf oclif.manifest.json", 42 | "posttest": "yarn lint", 43 | "prepack": "yarn build", 44 | "preversion": "yarn postpublish", 45 | "test": "mocha --forbid-only \"test/**/*.test.ts\"", 46 | "version": "oclif-dev readme && git add README.md" 47 | }, 48 | "main": "lib/index.js", 49 | "types": "lib/index.d.ts", 50 | "files": [ 51 | "/lib", 52 | "/oclif.manifest.json" 53 | ], 54 | "oclif": { 55 | "commands": "./lib/commands", 56 | "bin": "sage", 57 | "devPlugins": [ 58 | "@oclif/plugin-help" 59 | ], 60 | "topics": { 61 | "preset": { 62 | "description": "Swap the front-end scaffolding for the theme" 63 | } 64 | }, 65 | "repositoryPrefix": "<%- repo %>/blob/v<%- version %>/packages/preset/<%- commandPath %>" 66 | }, 67 | "gitHead": "397ccc8faf06049b3d599ee9557956bd0f77a8a4" 68 | } 69 | -------------------------------------------------------------------------------- /packages/preset/src/commands/preset/index.ts: -------------------------------------------------------------------------------- 1 | import { Preset as Command } from '@sage-cli/cli-utils'; 2 | 3 | export default class Preset extends Command { 4 | static description = 'Swap the front-end scaffolding for the theme' 5 | 6 | static examples = [ 7 | `$ sage preset:bootstrap`, 8 | ] 9 | 10 | static flags = { 11 | ...Command.flags, 12 | } 13 | 14 | async configure() { 15 | this.preset = await this.prompt('Which preset would you like to install?', Object.keys(this.presets).map(command => command.substr(7)).join('|')); 16 | } 17 | 18 | async validate() { 19 | if (! this.preset || ! this.presets[`preset:${this.preset}`]) { 20 | this.error('You must specify a valid preset.'); 21 | } 22 | } 23 | 24 | async execute() { 25 | if (this.flags.clean) { 26 | await this.clean(); 27 | } 28 | await this.exec(this.presets[`preset:${this.preset}`].load()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/preset/src/index.ts: -------------------------------------------------------------------------------- 1 | import Preset from './commands/preset'; 2 | export default Preset; 3 | -------------------------------------------------------------------------------- /packages/preset/test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require ts-node/register 2 | --watch-extensions ts 3 | --recursive 4 | --reporter spec 5 | --timeout 5000 6 | -------------------------------------------------------------------------------- /packages/preset/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "compilerOptions": { 4 | "sourceMap": true, 5 | "noEmit": true 6 | }, 7 | "references": [ 8 | {"path": ".."} 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/preset/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/preset/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@oclif/tslint" 3 | } 4 | -------------------------------------------------------------------------------- /packages/setup/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [1.0.0-alpha.1](https://github.com/roots/sage-cli/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2019-07-11) 7 | 8 | **Note:** Version bump only for package @sage-cli/plugin-setup 9 | 10 | 11 | 12 | 13 | 14 | # 1.0.0-alpha.0 (2019-07-11) 15 | 16 | **Note:** Version bump only for package @sage-cli/plugin-setup 17 | -------------------------------------------------------------------------------- /packages/setup/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © Roots 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/setup/README.md: -------------------------------------------------------------------------------- 1 | Preset plugin for [`sage`](https://roots.io/sage/cli) 2 | ================ 3 | 4 | Swap the front-end scaffolding for the theme. 5 | 6 | [![Version](https://img.shields.io/npm/v/@sage-cli/plugin-preset.svg)](https://npmjs.org/package/@sage-cli/plugin-preset) 7 | [![Known Vulnerabilities](https://snyk.io/test/npm/@sage-cli/plugin-preset/badge.svg)](https://snyk.io/test/npm/@sage-cli/plugin-preset) 8 | [![Downloads/week](https://img.shields.io/npm/dw/@sage-cli/plugin-preset.svg)](https://npmjs.org/package/@sage-cli/plugin-preset) 9 | [![License](https://img.shields.io/npm/l/@sage-cli/plugin-preset.svg)](https://github.com/roots/sage-cli/blob/master/packages/preset/package.json) 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ```sh-session 18 | $ npm install -g @sage-cli/plugin-setup 19 | $ sage COMMAND 20 | running command... 21 | $ sage (-v|--version|version) 22 | @sage-cli/plugin-setup/1.0.0-alpha.1 linux-x64 node-v10.15.3 23 | $ sage --help [COMMAND] 24 | USAGE 25 | $ sage COMMAND 26 | ... 27 | ``` 28 | 29 | 30 | 31 | * [`sage setup`](#sage-setup) 32 | 33 | ## `sage setup` 34 | 35 | Sets theme headers and other metadata. 36 | 37 | ``` 38 | USAGE 39 | $ sage setup 40 | 41 | OPTIONS 42 | -Y, --suppress Suppress warnings when overwriting or deleting files 43 | -a, --author=author Author 44 | -d, --description=description Description 45 | -i, --text_domain=text_domain Text Domain 46 | -l, --license=license Theme license 47 | -n, --name=name Theme Name 48 | -p, --template=template Template (parent theme) 49 | -t, --tags=tags Tags (comma separated) 50 | -u, --uri=uri Theme URI 51 | -v, --version=version Theme Version 52 | --author_uri=author_uri Author URI 53 | --banner=banner Banner (appears after the headers) 54 | --force Disregard all failsafes. 55 | --license_uri=license_uri License URI 56 | --no-interaction Do not ask any interactive questions 57 | --path=path Custom path to Sage theme 58 | 59 | EXAMPLE 60 | $ sage setup --name=Sage --version=10.0.0 --uri=https://roots.io/ --description='Sage is a WordPress starter theme' 61 | --author='Roots ' --license='MIT ' 62 | --tags=wordpress,sage,bootstrap 63 | ``` 64 | 65 | _See code: [src/commands/setup/index.ts](https://github.com/roots/sage-cli/blob/v1.0.0-alpha.1/packages/setup/src/commands/setup/index.ts)_ 66 | 67 | -------------------------------------------------------------------------------- /packages/setup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sage-cli/plugin-setup", 3 | "description": "Performs post-installation operations for Sage.", 4 | "version": "1.0.0-alpha.1", 5 | "author": "QWp6t", 6 | "bugs": "https://github.com/roots/sage-cli/issues", 7 | "engines": { 8 | "node": ">=8.0.0" 9 | }, 10 | "homepage": "https://roots.io/sage/cli", 11 | "keywords": [ 12 | "sage", 13 | "sage-cli" 14 | ], 15 | "license": "MIT", 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/roots/sage-cli.git", 22 | "directory": "packages/setup" 23 | }, 24 | "dependencies": { 25 | "@sage-cli/cli-utils": "^1.0.0-alpha.1", 26 | "slugify": "^1" 27 | }, 28 | "devDependencies": { 29 | "@oclif/dev-cli": "^1", 30 | "@oclif/test": "^1", 31 | "@oclif/tslint": "^3", 32 | "rimraf": "^3", 33 | "ts-node": "^8", 34 | "typescript": "^3" 35 | }, 36 | "scripts": { 37 | "clean": "rimraf oclif.manifest.json lib tsconfig.tsbuildinfo *-error.log", 38 | "prebuild": "yarn clean", 39 | "build": "tsc -b", 40 | "postbuild": "oclif-dev manifest && oclif-dev readme", 41 | "lint": "tsc -p test --noEmit && tslint -p test -t stylish", 42 | "postpublish": "rimraf oclif.manifest.json", 43 | "posttest": "yarn lint", 44 | "prepack": "yarn build", 45 | "preversion": "yarn postpublish", 46 | "test": "mocha --forbid-only \"test/**/*.test.ts\"", 47 | "version": "oclif-dev readme && git add README.md" 48 | }, 49 | "main": "lib/index.js", 50 | "types": "lib/index.d.ts", 51 | "files": [ 52 | "/lib", 53 | "/oclif.manifest.json" 54 | ], 55 | "oclif": { 56 | "commands": "./lib/commands", 57 | "bin": "sage", 58 | "devPlugins": [ 59 | "@oclif/plugin-help" 60 | ], 61 | "topics": { 62 | "setup": { 63 | "description": "Sets theme headers and other metadata." 64 | } 65 | }, 66 | "repositoryPrefix": "<%- repo %>/blob/v<%- version %>/packages/setup/<%- commandPath %>" 67 | }, 68 | "gitHead": "397ccc8faf06049b3d599ee9557956bd0f77a8a4" 69 | } 70 | -------------------------------------------------------------------------------- /packages/setup/src/commands/setup/index.ts: -------------------------------------------------------------------------------- 1 | import { flags } from '@oclif/command'; 2 | import { Command } from '@sage-cli/cli-utils'; 3 | import { ThemeHeaders } from '../../theme-headers'; 4 | 5 | export default class Setup extends Command { 6 | static description = 'Sets theme headers and other metadata.' 7 | 8 | static examples = [ 9 | `$ sage setup --name=Sage --version=10.0.0 --uri=https://roots.io/ --description='Sage is a WordPress starter theme' --author='Roots ' --license='MIT ' --tags=wordpress,sage,bootstrap`, 10 | ] 11 | 12 | static args = [ 13 | ...Command.args, 14 | ] 15 | 16 | static flags = { 17 | ...Command.flags, 18 | // interactive flags 19 | name: flags.string({ char: 'n', description: 'Theme Name' }), 20 | version: flags.string({ char: 'v', description: 'Theme Version' }), 21 | uri: flags.string({ char: 'u', description: 'Theme URI' }), 22 | description: flags.string({ char: 'd', description: 'Description' }), 23 | author: flags.string({ char: 'a', description: 'Author' }), 24 | license: flags.string({ char: 'l', description: 'Theme license' }), 25 | text_domain: flags.string({ char: 'i', description: 'Text Domain' }), 26 | tags: flags.string({ char: 't', description: 'Tags (comma separated)' }), 27 | // advanced flags 28 | template: flags.string({ char: 'p', description: 'Template (parent theme)' }), 29 | author_uri: flags.string({ description: 'Author URI' }), 30 | license_uri: flags.string({ description: 'License URI' }), 31 | banner: flags.string({ description: 'Banner (appears after the headers)' }), 32 | } 33 | 34 | protected should_write_meta:boolean = false; 35 | protected headers:ThemeHeaders = new ThemeHeaders(ThemeHeaders.defaults); 36 | protected stylesheet_path:string = `${process.cwd()}/resources/style.css`; 37 | 38 | async configure() { 39 | const meta = this.sage ? this.sage.config.theme : null; 40 | const defaults = new ThemeHeaders(meta || ThemeHeaders.defaults); 41 | 42 | const name = this.flags.name || await this.prompt(Setup.flags.name.description, defaults.name); 43 | const version = this.flags.version || await this.prompt(Setup.flags.version.description, defaults.version); 44 | const uri = this.flags.uri || await this.prompt(Setup.flags.uri.description, defaults.uri); 45 | const description = this.flags.description || await this.prompt(Setup.flags.description.description, defaults.description); 46 | const author = this.flags.author || await this.prompt(Setup.flags.author.description, `${ThemeHeaders.getResource(defaults.author).name} <${ThemeHeaders.getResource(defaults.author).uri}>` || ''); 47 | const author_uri = this.flags.author_uri || ThemeHeaders.getResource(author).uri || await this.prompt(Setup.flags.author_uri.description, defaults.header('author_uri') || ''); 48 | const license = this.flags.license || await this.prompt(Setup.flags.license.description, `${ThemeHeaders.getResource(defaults.license).name} <${ThemeHeaders.getResource(defaults.license).uri}>` || ''); 49 | const license_uri = this.flags.license_uri || ThemeHeaders.getResource(license).uri || await this.prompt(Setup.flags.license_uri.description, defaults.header('license_uri') || ''); 50 | const text_domain = this.flags.text_domain || await this.prompt(Setup.flags.text_domain.description, defaults.text_domain); 51 | const tags = this.flags.tags || await this.prompt(Setup.flags.tags.description, Array.from(defaults.tags || []).join(', ')); 52 | const template = this.flags.template; 53 | const banner = this.flags.banner || defaults.banner; 54 | 55 | this.headers = new ThemeHeaders({ 56 | name, version, uri, description, author, author_uri, license, license_uri, text_domain, template, tags, banner 57 | }); 58 | 59 | this.should_write_meta = !! meta; 60 | this.stylesheet_path = this.files.exists(`${this.files.path}/style.css`) ? `${this.files.path}/style.css` : `${this.files.path}/resources/style.css`; 61 | this.suppress = this.suppress || ! this.files.exists(this.stylesheet_path); 62 | } 63 | 64 | async execute() { 65 | if (! this.should_write_meta) { 66 | this.files.write(`${this.files.path}/.sagerc`, JSON.stringify(Object.assign(this.sage || {}, { theme: this.headers }), null, 2)); 67 | } 68 | 69 | this.files.write(this.stylesheet_path, this.headers); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /packages/setup/src/index.ts: -------------------------------------------------------------------------------- 1 | export default {} 2 | -------------------------------------------------------------------------------- /packages/setup/src/theme-headers.ts: -------------------------------------------------------------------------------- 1 | import slugify from 'slugify'; 2 | 3 | type Resource = { 4 | uri:string, 5 | name: string, 6 | }; 7 | 8 | type MetaConfig = { 9 | name?: string, 10 | version?: string, 11 | uri?: string, 12 | description?: string, 13 | author?: string | Resource, 14 | author_uri?: string, 15 | license?: string | Resource, 16 | license_uri?: string, 17 | tags?: string | string[], 18 | text_domain?: string, 19 | template?: string, 20 | banner?: string, 21 | }; 22 | 23 | type HeaderContent = string|null|undefined; 24 | type Header = { header:string, key:string, content:HeaderContent }; 25 | type RawHeaders = { [key:string] : Header }; 26 | 27 | export class ThemeHeaders { 28 | public name: string; 29 | public version?: string; 30 | public uri?: string; 31 | public description?: string; 32 | public author: Resource; 33 | public license: Resource; 34 | public tags?: string[]; 35 | public text_domain: string; 36 | public template?: string; 37 | public banner: string; 38 | 39 | static defaults = { 40 | name: "Sage Starter Theme", 41 | version: "10.0.0", 42 | uri: "https://roots.io/sage/", 43 | description: "Sage is a WordPress starter theme.", 44 | author: "Roots ", 45 | license: "MIT ", 46 | tags: ["sage", "bootstrap"], 47 | text_domain: "sage", 48 | banner: "This WordPress theme was built using tools provided by Roots.\n\nhttps://roots.io/" 49 | } 50 | 51 | constructor(config:MetaConfig) { 52 | this.name = config.name || ThemeHeaders.defaults.name; 53 | this.version = config.version || ThemeHeaders.defaults.version; 54 | this.uri = config.uri || ThemeHeaders.defaults.uri; 55 | this.description = config.description || ThemeHeaders.defaults.description; 56 | this.author = ThemeHeaders.getResource(config.author || ThemeHeaders.defaults.author); 57 | this.license = ThemeHeaders.getResource(config.license || ThemeHeaders.defaults.license); 58 | this.text_domain = config.text_domain || slugify(this.name); 59 | this.template = config.template; 60 | this.banner = config.banner || ThemeHeaders.defaults.banner; 61 | 62 | this.tags = (typeof config.tags === 'string') ? config.tags.split(',') : config.tags; 63 | if (this.tags) { 64 | this.tags = this.tags.map(tag => tag.toLowerCase().trim()); 65 | } 66 | } 67 | 68 | public static getResource(config: string | Resource) : Resource { 69 | if (typeof config !== 'string') { 70 | return config; 71 | } 72 | const name_uri: Resource = { name: '', uri: ''}; 73 | 74 | const splitString = config.split(/[<>]/g).filter(Boolean); 75 | 76 | if (splitString.length === 0) { 77 | return { name: '', uri: '' }; 78 | } 79 | 80 | if (splitString.length === 1) { 81 | return { 82 | name: (splitString.pop() || '').trim(), 83 | uri: '' 84 | }; 85 | } 86 | 87 | name_uri.uri = (splitString.pop() || '').trim(); 88 | name_uri.name = splitString.join('').trim(); 89 | 90 | return name_uri; 91 | } 92 | 93 | public all(): RawHeaders { 94 | return { 95 | name: { 96 | header: 'Theme Name', 97 | key: 'name', 98 | content: this.name, 99 | }, 100 | uri: { 101 | header: 'Theme URI', 102 | key: 'uri', 103 | content: this.uri, 104 | }, 105 | author: { 106 | header: 'Author', 107 | key: 'author', 108 | content: this.author.name, 109 | }, 110 | author_uri: { 111 | header: 'Author URI', 112 | key: 'author_uri', 113 | content: this.author.uri, 114 | }, 115 | description: { 116 | header: 'Description', 117 | key: 'description', 118 | content: this.description, 119 | }, 120 | version: { 121 | header: 'Version', 122 | key: 'version', 123 | content: this.version, 124 | }, 125 | license: { 126 | header: 'License', 127 | key: 'license', 128 | content: this.license.name, 129 | }, 130 | license_uri: { 131 | header: 'License URI', 132 | key: 'license_uri', 133 | content: this.license.uri, 134 | }, 135 | tags: { 136 | header: 'Tags', 137 | key: 'tags', 138 | content: Array.from(this.tags || []).join(', '), 139 | }, 140 | text_domain: { 141 | header: 'Text Domain', 142 | key: 'text_domain', 143 | content: this.text_domain, 144 | }, 145 | template: { 146 | header: 'Template', 147 | key: 'template', 148 | content: this.template, 149 | } 150 | }; 151 | } 152 | 153 | public header(header: string): HeaderContent { 154 | const filtered = this.filter((_unused, current:Header) => (current.header === header) || current.key === header); 155 | return Object.keys(filtered) 156 | .reduce((_unused:HeaderContent, key:string) => filtered[key].content, null); 157 | } 158 | 159 | public filter(callable:(content: HeaderContent, header: Header, headers: RawHeaders) => boolean = Boolean) : RawHeaders { 160 | const all = this.all(); 161 | return Object.keys(all) 162 | .filter(header => callable(all[header].content, all[header], all)) 163 | .reduce((headers: RawHeaders, header: string) => { 164 | headers[header] = all[header]; 165 | return headers; 166 | }, {}); 167 | } 168 | 169 | public toString(): string { 170 | const headers = this.filter(); 171 | return ` 172 | /* 173 | ${ 174 | Object.keys(headers) 175 | .map(header => `${headers[header].header}: ${headers[header].content}`) 176 | .concat(['', this.banner]) 177 | .join("\n").trim() 178 | } 179 | */ 180 | `; 181 | } 182 | } 183 | 184 | export default ThemeHeaders; 185 | -------------------------------------------------------------------------------- /packages/setup/test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require ts-node/register 2 | --watch-extensions ts 3 | --recursive 4 | --reporter spec 5 | --timeout 5000 6 | -------------------------------------------------------------------------------- /packages/setup/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "compilerOptions": { 4 | "sourceMap": true, 5 | "noEmit": true 6 | }, 7 | "references": [ 8 | {"path": ".."} 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/setup/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/setup/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@oclif/tslint" 3 | } 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es2017", 5 | "module": "commonjs", 6 | // "lib": ["esnext"], 7 | // "allowJs": true, 8 | // "checkJs": true, 9 | // "jsx": "preserve", 10 | "declaration": true, 11 | // "declarationMap": true, 12 | "pretty": true, 13 | // "sourceMap": true, 14 | // "outFile": "./", 15 | // "outDir": "lib", 16 | // "rootDir": "src", 17 | "composite": true, 18 | // "removeComments": true, 19 | // "noEmit": true, 20 | "importHelpers": true, 21 | // "downlevelIteration": true, 22 | // "isolatedModules": true, 23 | 24 | /* Strict Type-Checking Options */ 25 | "strict": true, 26 | // "noImplicitAny": true, 27 | // "strictNullChecks": true, 28 | // "strictFunctionTypes": true, 29 | // "strictBindCallApply": true, 30 | // "strictPropertyInitialization": true, 31 | // "noImplicitThis": true, 32 | // "alwaysStrict": true, 33 | // "forceConsistentCasingInFileNames": true, 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, 37 | // "noUnusedParameters": true, 38 | // "noImplicitReturns": true, 39 | // "noFallthroughCasesInSwitch": true, 40 | 41 | /* Module Resolution Options */ 42 | "moduleResolution": "node", 43 | "baseUrl": "./", 44 | "paths": { "@sage-cli/*": ["packages/*"] }, 45 | // "rootDirs": [], 46 | // "typeRoots": [], 47 | // "types": [], 48 | // "allowSyntheticDefaultImports": true, 49 | "esModuleInterop": true, 50 | // "preserveSymlinks": true, 51 | 52 | /* Source Map Options */ 53 | // "sourceRoot": "", 54 | // "mapRoot": "", 55 | // "inlineSourceMap": true, 56 | // "inlineSources": true, 57 | 58 | /* Experimental Options */ 59 | // "experimentalDecorators": true, 60 | // "emitDecoratorMetadata": true, 61 | } 62 | } 63 | --------------------------------------------------------------------------------