Skip to content
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
62 changes: 62 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"name": "Tailor - Content Element",
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm",
"features": {
"ghcr.io/devcontainers-extra/features/pnpm:2": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"forwardPorts": [8080, 8010, 8020, 8030],
"portsAttributes": {
"8080": {
"label": "Content Element Kit preview",
"onAutoForward": "notify"
},
"8010": {
"label": "Edit runtime",
"onAutoForward": "silent"
},
"8020": {
"label": "Display runtime",
"onAutoForward": "silent"
},
"8030": {
"label": "Server runtime",
"onAutoForward": "silent"
}
},
"postCreateCommand": "pnpm install --frozen-lockfile && pnpm build",
"postAttachCommand": "/bin/bash .devcontainer/setup.sh && pnpm dev",
"customizations": {
"vscode": {
"settings": {
"editor.formatOnSave": true,
"eslint.enable": true,
"prettier.requireConfig": true,
"files.exclude": {
"**/.pnpm": true,
"**/node_modules": true
},
"workbench.colorTheme": "One Dark Pro",
"oneDarkPro.editorFontLigatures": true,
"oneDarkPro.bold": true,
"oneDarkPro.italic": true,
"editor.fontSize": 20,
"editor.fontFamily": "'Dank Mono', 'Fira Code', monospace",
"editor.fontLigatures": true
},
"extensions": [
"akamud.vscode-theme-onedark",
"zhuangtongfa.Material-theme",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"mikestead.dotenv",
"sainoba.px-to-rem",
"stylelint.vscode-stylelint",
"zhuangtongfa.material-theme",
"EditorConfig.EditorConfig",
"Vue.volar",
"GitHub.copilot"
]
}
}
}
15 changes: 15 additions & 0 deletions .devcontainer/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
# This script sets port 8030 to public in GitHub Codespaces to handle preflight request issues.
# @see https://github.com/community/community/discussions/15351

set -euo pipefail

# Default server port assumed for codespace environment
DEFAULT_SERVER_PORT=8030

if [[ -n "${CODESPACE_NAME:-}" ]]; then
echo "Setting port $DEFAULT_SERVER_PORT to public in Codespace: $CODESPACE_NAME"
gh codespace ports visibility "$DEFAULT_SERVER_PORT:public" -c "$CODESPACE_NAME"
else
echo "Not running in a Codespace, skipping port visibility change."
fi
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ EDIT_RUNTIME_URL=http://localhost:8002
DISPLAY_RUNTIME_URL=http://localhost:8003
SERVER_RUNTIME_URL=http://localhost:8004

# AI service configuration
# If AI_UI_ENABLED is set to true, the AI service will be enabled and model id
# and secret key must be provided.
AI_UI_ENABLED=
AI_MODEL_ID=
AI_SECRET_KEY=

# Content Element env variables; TCE_ prefix is required
# Will be loaded to the server runtime
TCE_TEST=123
2 changes: 1 addition & 1 deletion .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ runs:
- name: Setup node to enable caching
uses: actions/setup-node@v4
with:
node-version: 22.12
node-version: 24
cache: 'pnpm'
cache-dependency-path: './pnpm-lock.yaml'
- name: Install dependencies
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules/
.pnpm-store
/dist/

# OS
Expand All @@ -14,6 +15,7 @@ node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
nohup.out

# Editor directories and files
.idea
Expand Down
File renamed without changes.
44 changes: 22 additions & 22 deletions bin/index.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#! /usr/bin/env node
const chalk = require("chalk");
const degit = require("degit");
const shell = require("shelljs");
const chalk = require('chalk');
const degit = require('degit');
const shell = require('shelljs');

const {
setupSnippet,
Expand All @@ -11,67 +11,67 @@ const {
getPackageJson,
getPackageName,
SUCCESS_CODE,
} = require("./utils.cjs");
} = require('./utils.cjs');

function validateEnvironment() {
["git", "node", "pnpm"].forEach((prerequisite) => {
['git', 'node', 'pnpm'].forEach((prerequisite) => {
if (!shell.which(prerequisite)) {
exitOnError(`This script requires ${prerequisite}`);
}
});
}

async function cloneRepository() {
shell.echo(formatSuccessLog("1/4 Cloning respository"));
shell.echo(formatSuccessLog('1/4 Cloning respository'));
const name = await getPackageName();
await degit("tailor-cms/tce-template", { mode: "git" }).clone(name);
await degit('tailor-cms/tce-template', { mode: 'git' }).clone(name);
shell.cd(`./${name}`);
await updatePackageJson({ name });
}

function installDependencies() {
shell.echo(formatSuccessLog("\n2/4 Installing dependencies"));
const installRootDepsCommand = shell.exec("pnpm i");
shell.echo(formatSuccessLog('\n2/4 Installing dependencies'));
const installRootDepsCommand = shell.exec('pnpm i');
if (installRootDepsCommand.code !== SUCCESS_CODE) {
exitOnError("Installing dependencies via pnpm failed");
exitOnError('Installing dependencies via pnpm failed');
}
const buildDepsCommand = shell.exec("pnpm build");
const buildDepsCommand = shell.exec('pnpm build');
if (buildDepsCommand.code !== SUCCESS_CODE) {
exitOnError("Building dependencies via pnpm failed");
exitOnError('Building dependencies via pnpm failed');
}
}

async function runSetup() {
shell.echo(formatSuccessLog("\n3/4 Setting up project"));
shell.echo(formatSuccessLog('\n3/4 Setting up project'));
try {
const answer = await setupSnippet.run();
shell.echo(answer.result);
const packageInfo = JSON.parse(answer.result);
await updatePackageJson(packageInfo);
const subpackages = ['edit', 'display', 'server', 'manifest'];
for (const packageName of subpackages) {
await updatePackageJson(packageInfo, `./packages/${packageName}`)
await updatePackageJson(packageInfo, `./packages/${packageName}`);
}
} catch {
exitOnError("Project setup failed");
exitOnError('Project setup failed');
}
}

async function cleanup() {
shell.echo(formatSuccessLog("\n4/4 Cleanup"));
await updatePackageJson({ dependencies: {} });
const deleteBinCommand = shell.exec("rm -rf bin");
shell.echo(formatSuccessLog('\n4/4 Cleanup'));
await updatePackageJson({ dependencies: {}, bin: {} });
const deleteBinCommand = shell.exec('rm -rf bin');
if (deleteBinCommand.code !== SUCCESS_CODE) {
exitOnError("Cleanup failed");
exitOnError('Cleanup failed');
}
}

async function displayInstructions() {
const packageName = (await getPackageJson()).name;
shell.echo(chalk.green("Done!\n"));
shell.echo("Your next steps are:");
shell.echo(chalk.green('Done!\n'));
shell.echo('Your next steps are:');
shell.echo(chalk.blue(`📂 cd ${packageName}`));
shell.echo(`🚀 Start development server with ${chalk.blue("pnpm dev")}`);
shell.echo(`🚀 Start development server with ${chalk.blue('pnpm dev')}`);
}

const SCRIPT_STEPS = [
Expand Down
28 changes: 14 additions & 14 deletions bin/utils.cjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const readline = require("node:readline");
const { Snippet } = require('enquirer');
const chalk = require('chalk');
const PackageJson = require('@npmcli/package-json');
const shell = require('shelljs');
const validatePackageName = require('validate-npm-package-name');

const { Snippet } = require("enquirer");
const chalk = require("chalk");
const PackageJson = require("@npmcli/package-json");
const shell = require("shelljs");
const validatePackageName = require("validate-npm-package-name");
const readline = require('node:readline');

const SUCCESS_CODE = 0;
const ERROR_CODE = 1;
Expand All @@ -30,8 +30,8 @@ const rl = readline.createInterface({
const prompt = (query) => new Promise((resolve) => rl.question(query, resolve));

const setupSnippet = new Snippet({
name: "package.json",
message: "Fill out the fields in package.json",
name: 'package.json',
message: 'Fill out the fields in package.json',
required: true,
template: `{
"description": "\${description}",
Expand All @@ -42,28 +42,28 @@ const setupSnippet = new Snippet({

async function getPackageJson() {
try {
const pkgJson = await PackageJson.load("./");
const pkgJson = await PackageJson.load('./');
return pkgJson.content;
} catch {
exitOnError("Error loading package.json");
exitOnError('Error loading package.json');
}
}

async function updatePackageJson(data, path = "./") {
async function updatePackageJson(data, path = './') {
try {
const pkgJson = await PackageJson.load(path);
pkgJson.update(data);
await pkgJson.save();
} catch (err) {
exitOnError("Error updating package.json: " + err.message);
exitOnError('Error updating package.json: ' + err.message);
}
}

async function getPackageName() {
const name = await prompt(chalk.cyan("Enter project name: "));
const name = await prompt(chalk.cyan('Enter project name: '));
if (!validatePackageName(name).validForNewPackages) {
shell.echo(
formatErrorLog("The provided name must be a valid NPM package name.")
formatErrorLog('The provided name must be a valid NPM package name.'),
);
return getPackageName();
}
Expand Down
18 changes: 18 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import tailorConfig from '@tailor-cms/eslint-config/base.js';

export default [
...tailorConfig,
{
ignores: ['dist/**', 'packages/**'],
},
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
ecmaVersion: 'latest',
sourceType: 'module',
},
},
},
];
42 changes: 21 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,40 @@
}
},
"scripts": {
"dev": "concurrently 'pnpm boot:cek' 'pnpm boot:display' -n cek,display-runtime -c blue,cyan",
"boot:cek": "cd ./node_modules/@tailor-cms/tce-boot && pnpm start",
"boot:display": "export TCE_DISPLAY_DIR=${PWD}/packages/display/dist && cd ./node_modules/@tailor-cms/tce-display-runtime && pnpm dev",
"dev": "pnpm boot:cek",
"boot:cek": "cd ./node_modules/@tailor-cms/tce-boot && pnpm start --default-display",
"build": "pnpm -r run build",
"lint": "pnpm -r run lint",
"lint:fix": "pnpm -r run lint --fix",
"lint": "pnpm -r run lint && eslint .",
"lint:fix": "pnpm -r run lint --fix && eslint . --fix",
"nuke:dist": "pnpm -r run nuke:dist",
"nuke": "pnpm -r run nuke && pnpm dlx del-cli node_modules",
"test": "pnpm playwright test --config ./test/playwright.config.ts"
},
"bin": {
"@tailor-cms/tce-template": "bin/index.cjs"
},
"dependencies": {
"@npmcli/package-json": "^6.1.1",
"chalk": "^4.1.2",
"@npmcli/package-json": "^6.2.0",
"chalk": "^5.4.1",
"degit": "^2.8.4",
"enquirer": "^2.4.1",
"has-flag": "^5.0.1",
"shelljs": "^0.8.5",
"validate-npm-package-name": "^6.0.0"
"shelljs": "^0.10.0",
"validate-npm-package-name": "^6.0.1"
},
"devDependencies": {
"@changesets/cli": "^2.27.12",
"@playwright/test": "1.50.1",
"@tailor-cms/eslint-config": "0.0.2",
"@tailor-cms/tce-boot": "1.0.7",
"@tailor-cms/tce-display-runtime": "0.6.13",
"@types/node": "^22.13.1",
"concurrently": "^9.1.2",
"dotenv": "^16.4.7",
"prettier": "3.5.0",
"typescript": "^5.7.3"
"@changesets/cli": "^2.29.5",
"@playwright/test": "1.53.2",
"@tailor-cms/cek-e2e": "^1.3.2",
"@tailor-cms/eslint-config": "1.1.2",
"@tailor-cms/tce-boot": "1.3.2",
"@types/node": "^24.0.12",
"dotenv": "^17.1.0",
"eslint": "^9.30.1",
"prettier": "^3.6.2",
"typescript": "^5.8.3"
},
"publishConfig": {
"access": "public"
},
"packageManager": "pnpm@9.0.6+sha512.f6d863130973207cb7a336d6b439a242a26ac8068077df530d6a86069419853dc1ffe64029ec594a9c505a3a410d19643c870aba6776330f5cfddcf10a9c1617"
"packageManager": "pnpm@10.12.3"
}
21 changes: 0 additions & 21 deletions packages/display/.eslintrc.cjs

This file was deleted.

19 changes: 19 additions & 0 deletions packages/display/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import tailorConfig from '@tailor-cms/eslint-config';

export default [
...tailorConfig,
{
ignores: ['**/components.d.ts', 'dist/**'],
},
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
ecmaVersion: 'latest',
sourceType: 'module',
extraFileExtensions: ['.vue'],
},
},
},
];
Loading
Loading