Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit f429ce5

Browse files
Chris McConnellninggao
authored andcommitted
Add the ability to override generated templates (#500)
in order to support transform scenarios.
1 parent 569542b commit f429ce5

File tree

8 files changed

+76
-9
lines changed

8 files changed

+76
-9
lines changed

packages/cli/test/fixtures/lastversioncheck/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@
1414
"init": "../../../src/hooks/init/inithook"
1515
}
1616
},
17-
"lastversioncheck": "2020-01-27T19:18:56.498Z"
17+
"lastversioncheck": "2020-01-28T20:21:57.736Z"
1818
}

packages/dialog/src/commands/dialog/generate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default class GenerateDialog extends Command {
2424
locale: flags.string({ char: 'l', description: 'Locales to generate. [default: en-us]', multiple: true }),
2525
output: flags.string({ char: 'o', description: 'Output path for where to put generated .lu, .lg, .qna and .dialog files. [default: .]', default: '.', required: false }),
2626
schema: flags.string({ char: 's', description: 'Path to your app.schema file.', required: false }),
27-
templates: flags.string({ char: 't', description: 'Directory with templates to use for generating assets.', multiple: true }),
27+
templates: flags.string({ char: 't', description: 'Directory with templates to use for generating assets. With multiple directories, the first definition found wins. To include the standard templates, just use "standard" as a template directory name.', multiple: true }),
2828
verbose: flags.boolean({ description: 'Output verbose logging of files as they are processed', default: false }),
2929
}
3030

packages/dialog/src/commands/dialog/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ The generate command generates .lu, .lg, .qna and .dialog assets from a schema d
3030
- **--locale, -l** Locales to generate. By default en-us.
3131
- **--output, -o** Output directory.
3232
- **--schema, -s** Path to your app.schema file. By default is the standard SDK app.schema.
33-
- **--templates, -t** Directories with templates to use for generating assets.
33+
- **--templates, -t** Directories with templates to use for generating assets. First definition wins. A directory of "standard" includes the standard templates included with the tool.
3434
- **--verbose, -v** Verbose logging of generated files.
3535

3636
### Schema

packages/dialog/src/library/dialogGenerator.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ async function processLibraryTemplates(template: string, outPath: string, templa
124124
}
125125
}
126126
127+
// Add entry to the .lg generation context and return it.
128+
// This also ensures the file does not exist already.
127129
type FileRef = { name: string, fallbackName: string, fullName: string, relative: string }
128130
function addEntry(fullPath: string, outDir: string, tracker: any): FileRef | undefined {
129131
let ref: FileRef | undefined
@@ -181,6 +183,13 @@ async function processTemplate(
181183
filename = template.evaluateTemplate('filename', scope)
182184
}
183185
}
186+
187+
// See if generated file has been overridden in templates
188+
let existing = await findTemplate(filename, templateDirs, scope.locale)
189+
if (existing) {
190+
result = existing
191+
}
192+
184193
result = await processLibraryTemplates(result as string, outPath, templateDirs, outDir, scope, force, feedback)
185194
let dir = ppath.dirname(outPath)
186195
await fs.ensureDir(dir)
@@ -271,7 +280,7 @@ function expandSchema(schema: any, scope: any, path: string, inProperties: boole
271280
if (inProperties) {
272281
newPath += newPath === '' ? key : '.' + key;
273282
}
274-
let newVal = expandSchema(val, { ...scope, property: newPath}, newPath, key === 'properties', missingIsError, feedback)
283+
let newVal = expandSchema(val, { ...scope, property: newPath }, newPath, key === 'properties', missingIsError, feedback)
275284
newSchema[key] = newVal
276285
}
277286
} else if (typeof schema === 'string' && schema.startsWith('@{')) {
@@ -294,9 +303,21 @@ function expandSchema(schema: any, scope: any, path: string, inProperties: boole
294303
return newSchema
295304
}
296305

306+
function expandStandard(dirs: string[]): string[] {
307+
let expanded: string[] = []
308+
for (let dir of dirs) {
309+
if (dir === 'standard') {
310+
dir = ppath.join(__dirname, '../../templates')
311+
}
312+
expanded.push(dir)
313+
}
314+
return expanded;
315+
}
316+
297317
/**
298318
* Iterate through the locale templates and generate per property/locale files.
299319
* Each template file will map to <filename>_<property>.<ext>.
320+
* @param schemaPath Path to JSON Schema to use for generation.
300321
* @param outDir Where to put generated files.
301322
* @param metaSchema Schema to use when generating .dialog files
302323
* @param allLocales Locales to generate.
@@ -330,7 +351,7 @@ export async function generate(
330351
}
331352

332353
if (!templateDirs) {
333-
templateDirs = [ppath.join(__dirname, '../../templates')]
354+
templateDirs = ['standard']
334355
}
335356

336357
let op = 'Regenerating'
@@ -343,6 +364,7 @@ export async function generate(
343364
feedback(FeedbackType.message, `Templates: ${JSON.stringify(templateDirs)} `)
344365
feedback(FeedbackType.message, `App.schema: ${metaSchema} `)
345366
try {
367+
templateDirs = expandStandard(templateDirs)
346368
await fs.ensureDir(outDir)
347369
let schema = await processSchemas(schemaPath, templateDirs, feedback)
348370
schema.schema = expandSchema(schema.schema, {}, '', false, false, feedback)

packages/dialog/src/library/processSchemas.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ async function templateSchemas(templateDirs: string[], feedback: fg.Feedback): P
2121
let schema = await getSchema(file, feedback)
2222
let id: string = schema.$id || ppath.basename(file)
2323
if (!map[id]) {
24+
// First definition found wins
2425
map[id] = schema
2526
}
2627
}

packages/dialog/test/commands/dialog/generator.test.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,48 @@ import * as os from 'os'
1212
import * as ppath from 'path'
1313
import * as ft from '../../../src/library/schema'
1414
import * as gen from '../../../src/library/dialogGenerator'
15-
import { fail } from 'assert';
15+
import * as assert from 'assert';
1616

1717
describe('dialog:generate', async () => {
1818
let output = ppath.join(os.tmpdir(), 'sandwich.out')
1919
let schemaPath = 'test/commands/dialog/forms/sandwich.schema'
2020
let badSchema = 'test/commands/dialog/forms/bad-schema.schema'
2121
let notObject = 'test/commands/dialog/forms/not-object.schema'
22+
let override = 'test/commands/dialog/templates/override'
23+
2224
beforeEach(async () => {
2325
await fs.remove(output)
2426
})
2527

28+
it('Generation with override', async () => {
29+
try {
30+
await gen.generate(schemaPath, output, undefined, ['en-us'], [override, 'standard'], false, (type, msg) => {
31+
console.log(`${type}: ${msg}`)
32+
})
33+
let lg = await fs.readFile(ppath.join(output, 'en-us', 'sandwich-Bread.en-us.lg'))
34+
assert.ok(lg.toString().includes('What kind of bread?'), 'Did not override locale generated file')
35+
let dialog = await fs.readFile(ppath.join(output, 'sandwich-BreadAsk.dialog'))
36+
assert.ok(!dialog.toString().includes('priority'), 'Did not override top-level file')
37+
} catch (e) {
38+
assert.fail(e.message)
39+
}
40+
})
41+
2642
it('Generation', async () => {
2743
try {
2844
await gen.generate(schemaPath, output, undefined, ['en-us'], undefined, false, (type, msg) => {
2945
console.log(`${type}: ${msg}`)
3046
})
3147
} catch (e) {
32-
fail(e.message)
48+
assert.fail(e.message)
3349
}
3450
})
3551

52+
3653
it('Not object type', async () => {
3754
try {
3855
await ft.Schema.readSchema(notObject)
39-
fail('Did not detect bad schema');
56+
assert.fail('Did not detect bad schema');
4057
} catch (e) {
4158
expect(e.message).to.contain('must be of type object')
4259
}
@@ -45,7 +62,7 @@ describe('dialog:generate', async () => {
4562
it('Illegal schema', async () => {
4663
try {
4764
await ft.Schema.readSchema(badSchema)
48-
fail('Did not detect bad schema');
65+
assert.fail('Did not detect bad schema');
4966
} catch (e) {
5067
expect(e.message).to.contain('is not a valid JSON Schema')
5168
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# AskBread
2+
- What kind of bread?
3+
4+
# BreadName
5+
- bread
6+
7+
# Bread(val)
8+
- @{BreadEntity(val)}
9+
10+
[sandwich-BreadEntity.lg](sandwich-BreadEntity.lg)
11+
12+
[sandwich-common.lg](sandwich-common.lg)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
{
3+
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-dotnet/master/schemas/sdk.schema",
4+
"$kind": "Microsoft.OnEndOfActions",
5+
"condition":"!$Bread",
6+
"actions": [
7+
{
8+
"$kind": "Microsoft.Ask",
9+
"activity": "@{AskBread()}",
10+
"expectedProperties": [
11+
"Bread"
12+
]
13+
}
14+
]
15+
}

0 commit comments

Comments
 (0)