Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/schematic options #149

Merged
merged 17 commits into from
Jan 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion docs/blog.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ or
ng g @scullyio/init:markdown --name="my text" --slug="my slug id"
```

the following table shows all vailable options:

| option | description | default |
| -------------- | ------------------------------------------------------------------------------ | ------------------------ |
| `name` | define the name for the created module | 'blog' |
| `slug` | define the name for the `:slug` | 'id' |
| `routingScope` | set a routing scope (`Root` or `Child`) | Child |
| `sourceDir` | define a source dir name (when not used, `name` is used instead) | value from `name` option |
| `route` | define a route path before the `:slug` (when not used, `name` is used instead) | value from `name` option |

> If your markdown content will include code blocks, you may want the [code to be highlighted](utils.md).

## Generating New Blog Posts
Expand All @@ -41,7 +51,15 @@ To add a new blog post, run the following command.
ng g @scullyio/init:post --name="This is my post"
```

[Check how to integrate Scully with other tools.](utils.md)
the following table shows all vailable options:

| option | description | default |
| -------------- | ------------------------------------------------------ | --------- |
| `name` | define the name for the created post | 'blog-X' |
| `target` | define the target directory for the new post file | 'blog' |
| `metaDataFile` | use a meta data yaml template from a file for the post | undefined |

[Check how to integrate Scully with other tools.](utils.md)

---

Expand Down
8 changes: 8 additions & 0 deletions schematics/scully/assets/meta-data-template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title: override-me
thumbnail: assets/images/default.jpg
author: John Doe
mail: John.Doe@example.com
keywords:
- angular
- scully
language: en
46 changes: 42 additions & 4 deletions schematics/scully/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions schematics/scully/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
"@angular-devkit/core": "^9.0.0-rc.5",
"@angular-devkit/schematics": "^9.0.0-rc.5",
"@schematics/angular": "^9.0.0-rc.5",
"js-yaml": "^3.13.1",
"schematics-utilities": "^2.0.0"
},
"devDependencies": {
"@types/jasmine": "^3.3.9",
"@types/js-yaml": "^3.12.1",
"@types/node": "^8.0.31",
"jasmine": "^3.3.1",
"typescript": "~3.5.3"
Expand Down
18 changes: 13 additions & 5 deletions schematics/scully/src/add-blog/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
import {Rule, SchematicContext, Tree} from '@angular-devkit/schematics';
import {RunSchematicTask} from '@angular-devkit/schematics/tasks';
import {Schema} from './schema';
import {Schema as MarkownSchema} from '../create-markdown/schema';

export default function(options: any): Rule {
export default function(options: Schema): Rule {
return (tree: Tree, context: SchematicContext) => {
options.name = 'blog';
options.slug = 'slug';
context.addTask(new RunSchematicTask('create-markdown', options), []);
const makrdownOptions: MarkownSchema = {
name: 'blog',
slug: 'slug',
};

if (options.routingScope) {
makrdownOptions.routingScope = options.routingScope;
}
context.addTask(new RunSchematicTask('create-markdown', makrdownOptions), []);
};
}
2 changes: 1 addition & 1 deletion schematics/scully/src/add-blog/schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/schema",
"id": "add-component",
"id": "add-blog",
"title": "Scully add component schematic",
"type": "object",
"properties": {
Expand Down
6 changes: 6 additions & 0 deletions schematics/scully/src/add-blog/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface Schema {
/**
* The scope for the new routing module.
*/
routingScope?: 'Child' | 'Root';
}
57 changes: 42 additions & 15 deletions schematics/scully/src/add-post/index.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,54 @@
import { Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics';
import {strings} from '@angular-devkit/core';
import fs = require('fs');
import yaml = require('js-yaml');

import {Schema} from './schema';
import { strings } from '@angular-devkit/core';

export default function(options: Schema): Rule {
return (host: Tree, context: SchematicContext) => {
const name = options.name;
const nameDasherized = options.name ? strings.dasherize(options.name) : 'blog-X';
const targetDasherized = options.target ? strings.dasherize(options.target) : 'blog';
const filename = `./${targetDasherized}/${nameDasherized}.md`;

let metaData = {
title: '',
description: 'blog description',
publish: false,
};

const name = options.name ? options.name : 'blog-X';
const namD = options.name ? strings.dasherize(options.name) : 'blog-X';
if (!host.exists(`./blog/${namD}.md`)) {
host.create(`./blog/${namD}.md`,
`---
title: ${name}
description: blog description
publish: false
---
if (options.metaDataFile) {
let metaDataContents = '';
try {
metaDataContents = fs.readFileSync(options.metaDataFile, 'utf8');
} catch (e) {
throw new SchematicsException(`File ${options.metaDataFile} not found`);
}

try {
// check if yaml is valid
metaData = yaml.safeLoad(metaDataContents);
context.logger.info(`✅️ Meta Data File ${options.metaDataFile} successfully parsed`);
} catch (e) {
throw new SchematicsException(`${options.metaDataFile} contains no valid yaml`);
}
}

// set title from option and override if alreay in metaDataFile template
metaData.title = name;

if (!host.exists(filename)) {
const content = `---
${yaml.safeDump(metaData)}---

# ${name}
`);
context.logger.info(`✅️Blog ${name} file created`);
`;
host.create(filename, content);
context.logger.info(`✅️ Blog ${filename} file created`);
} else {
// return name exist
throw new SchematicsException(`${name} exist in your blog folder`);
throw new SchematicsException(`${nameDasherized} exist in your ${targetDasherized} folder`);
}
};
}

75 changes: 75 additions & 0 deletions schematics/scully/src/add-post/index_spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {HostTree} from '@angular-devkit/schematics';
import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing';
import {getFileContent} from '@schematics/angular/utility/test';
import * as path from 'path';

import {setupProject} from '../utils/test-utils';
import {Schema} from './schema';

const collectionPath = path.join(__dirname, '../collection.json');
const META_DATA_TEMPLATE_PATH = 'assets/meta-data-template.yml';

describe('add-post', () => {
const schematicRunner = new SchematicTestRunner('scully-schematics', collectionPath);
const project = 'foo';
const defaultOptions: Schema = {
name: 'Foo barBaz',
};
let appTree: UnitTestTree;
const expectedFileName = '/blog/foo-bar-baz.md';

beforeEach(async () => {
appTree = new UnitTestTree(new HostTree());
appTree = await setupProject(appTree, schematicRunner, project);
});

describe('when using the default options', () => {
beforeEach(async () => {
appTree = await schematicRunner.runSchematicAsync('post', defaultOptions, appTree).toPromise();
});

it('should create a new dasherized post', () => {
expect(appTree.files).toContain(expectedFileName);
const mdFileContent = getFileContent(appTree, expectedFileName);
expect(mdFileContent).toMatch(/title: Foo barBaz/g);
expect(mdFileContent).toMatch(/description: blog description/g);
expect(mdFileContent).toMatch(/publish: false/g);
});
});

describe('when using a different `target`', () => {
beforeEach(async () => {
appTree = await schematicRunner
.runSchematicAsync('post', {...defaultOptions, target: 'foo/bar'}, appTree)
.toPromise();
});

it('should create a new dasherized post inside the target dir', () => {
const expected = '/foo/bar/foo-bar-baz.md';
expect(appTree.files).toContain(expected);
const mdFileContent = getFileContent(appTree, expected);
expect(mdFileContent).toMatch(/title: Foo barBaz/g);
expect(mdFileContent).toMatch(/description: blog description/g);
expect(mdFileContent).toMatch(/publish: false/g);
});
});

describe('when using `metaDataFile` option', () => {
beforeEach(async () => {
appTree = await schematicRunner
.runSchematicAsync('post', {...defaultOptions, metaDataFile: META_DATA_TEMPLATE_PATH}, appTree)
.toPromise();
});

it('should add the meta data but keep title from options', () => {
expect(appTree.files).toContain(expectedFileName);
const mdFileContent = getFileContent(appTree, expectedFileName);
expect(mdFileContent).toMatch(/title: Foo barBaz/g);
expect(mdFileContent).toMatch(/thumbnail: assets\/images\/default\.jpg/g);
expect(mdFileContent).toMatch(/author: John Doe/g);
expect(mdFileContent).toMatch(/mail: John.Doe@example.com/g);
expect(mdFileContent).toMatch(/keywords:\s+-\ angular\s+-\ scully/s);
expect(mdFileContent).toMatch(/language: en/g);
});
});
});
16 changes: 14 additions & 2 deletions schematics/scully/src/add-post/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,20 @@
"name": {
"type": "string",
"description": "add the title for the post",
"x-prompt": "What title do you want to use for the post?"
"x-prompt": "What title do you want to use for the post?",
"default": "blog-X"
},
"target": {
"type": "string",
"description": "define the target directory for the new post file",
"x-prompt": "What's the target folder for this post?",
"default": "blog"
},
"metaDataFile": {
"type": "string",
"description": "use a meta data template file that's data will be added to the post",
"default": ""
}
},
"required": []
"required": ["name"]
}
16 changes: 15 additions & 1 deletion schematics/scully/src/add-post/schema.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
/**
* Scully ng-add-blog schematic
*/
export interface Schema {
name: string;
/**
* add the title for the post
*/
name: string;
/**
* define the target directory for the new post file
*/
target?: string;
/**
* use a meta data template file that's data will be added to the post
*/
metaDataFile?: string;
}
1 change: 1 addition & 0 deletions schematics/scully/src/collection.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
"id": "scully-schematics",
"schematics": {
"ng-add": {
"description": "Add scully to the application.",
Expand Down
Loading