Skip to content

Commit

Permalink
Feat: Generate Liquid Blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesmengo committed Dec 12, 2024
1 parent ff4e09b commit f1f8a88
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 13 deletions.
20 changes: 8 additions & 12 deletions packages/theme/src/cli/commands/theme/generate/block.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {themeFlags} from '../../../flags.js'
import ThemeCommand from '../../../utilities/theme-command.js'
import {hasRequiredThemeDirectories} from '../../../utilities/theme-fs.js'
import {generateBlock} from '../../../services/generate/blocks.js'
import {BLOCK_TYPES, promptForType} from '../../../utilities/generator.js'
import {Flags} from '@oclif/core'
import {globalFlags} from '@shopify/cli-kit/node/cli'
import {renderSelectPrompt, renderSuccess, renderTextPrompt, renderWarning} from '@shopify/cli-kit/node/ui'

const BLOCK_TYPES = ['text', 'image', 'video', 'product', 'collection']
import {renderTextPrompt, renderWarning} from '@shopify/cli-kit/node/ui'

export default class GenerateBlock extends ThemeCommand {
static summary = 'Creates and adds a new block file to your local theme directory'
Expand Down Expand Up @@ -57,16 +57,12 @@ export default class GenerateBlock extends ThemeCommand {
message: 'Name of the block',
}))

const choices = BLOCK_TYPES.map((type) => ({label: type, value: type}))
const type =
flags.type ??
(await renderSelectPrompt({
message: 'Type of block',
choices,
}))
const type = flags.type ?? (await promptForType('Type of block', BLOCK_TYPES))

renderSuccess({
body: [`Placeholder: Generating block with name: ${name}, type: ${type}`],
await generateBlock({
name,
type,
path: flags.path ?? '.',
})
}
}
43 changes: 43 additions & 0 deletions packages/theme/src/cli/services/generate/blocks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {generateBlock} from './blocks.js'
import {describe, expect, test, vi} from 'vitest'
import {fileExists, writeFile} from '@shopify/cli-kit/node/fs'
import {joinPath} from '@shopify/cli-kit/node/path'
import {outputInfo} from '@shopify/cli-kit/node/output'

vi.mock('@shopify/cli-kit/node/fs')
vi.mock('@shopify/cli-kit/node/path')
vi.mock('@shopify/cli-kit/node/output')

describe('generateBlock', () => {
const mockOptions = {
name: 'test-block',
type: 'basic',
path: 'theme',
} as const

test('creates a new block file with correct content', async () => {
vi.mocked(fileExists).mockResolvedValue(false)
vi.mocked(joinPath).mockReturnValue('theme/blocks/test-block.liquid')

await generateBlock(mockOptions)

const expectedContent = `{% schema %}
{
"name": "test-block",
"settings": []
}
{% endschema %}`

expect(writeFile).toHaveBeenCalledWith('theme/blocks/test-block.liquid', expectedContent)
expect(outputInfo).toHaveBeenCalledWith('Created block: theme/blocks/test-block.liquid')
})

test('throws error if block already exists', async () => {
vi.mocked(fileExists).mockResolvedValue(true)
vi.mocked(joinPath).mockReturnValue('theme/blocks/test-block.liquid')

await expect(generateBlock(mockOptions)).rejects.toThrow(
'Block test-block already exists at theme/blocks/test-block.liquid',
)
})
})
34 changes: 34 additions & 0 deletions packages/theme/src/cli/services/generate/blocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {BlockType} from '../../utilities/generator.js'
import {fileExists, writeFile} from '@shopify/cli-kit/node/fs'
import {joinPath} from '@shopify/cli-kit/node/path'
import {outputInfo} from '@shopify/cli-kit/node/output'

export interface BlockGeneratorOptions {

Check failure on line 6 in packages/theme/src/cli/services/generate/blocks.ts

View workflow job for this annotation

GitHub Actions / knip-reporter-annotations-check

packages/theme/src/cli/services/generate/blocks.ts#L6

'BlockGeneratorOptions' is an unused type
name: string
type: BlockType
path: string
}

export async function generateBlock(options: BlockGeneratorOptions) {
const blockPath = joinPath(options.path, 'blocks', `${options.name}.liquid`)

// Check if block already exists
if (await fileExists(blockPath)) {
throw new Error(`Block ${options.name} already exists at ${blockPath}`)
}

// Write the file
await writeFile(blockPath, generateBlockContent(options))
outputInfo(`Created block: ${blockPath}`)
}

function generateBlockContent(options: BlockGeneratorOptions): string {
const baseSchema = {
name: options.name,
settings: [],
}

return `{% schema %}
${JSON.stringify(baseSchema, null, 2)}
{% endschema %}`
}
2 changes: 1 addition & 1 deletion packages/theme/src/cli/utilities/generator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {renderSelectPrompt} from '@shopify/cli-kit/node/ui'

export const BLOCK_TYPES = ['text', 'image', 'video', 'product', 'collection']
export const BLOCK_TYPES = ['basic']
export const SECTION_TYPES = ['featured-collection', 'image-with-text', 'rich-text', 'custom']

Check failure on line 4 in packages/theme/src/cli/utilities/generator.ts

View workflow job for this annotation

GitHub Actions / knip-reporter-annotations-check

packages/theme/src/cli/utilities/generator.ts#L4

'SECTION_TYPES' is an unused export
export const TEMPLATE_TYPES = ['product', 'collection', 'page', 'blog', 'article', 'custom']

Expand Down

0 comments on commit f1f8a88

Please sign in to comment.