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

Setup TypeScript Infra #272

Merged
merged 3 commits into from
Dec 27, 2023
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
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,36 @@ jobs:
run: pnpm test:ember --launch ${{ matrix.browser }}
working-directory: test-app

typecheck:
name: '${{ matrix.typescript-scenario }}'
runs-on: ubuntu-latest
timeout-minutes: 2
continue-on-error: true
strategy:
fail-fast: false
matrix:
typescript-scenario:
- typescript@5.0
- typescript@5.1
- typescript@5.2
- typescript@5.3
- typescript@next

steps:
- uses: actions/checkout@v4
- uses: wyvox/action-setup-pnpm@v3
- run: pnpm build
- run: pnpm i -f # just in case
- name: 'Change TS to ${{ matrix.typescript-scenario }}'
working-directory: ./test-types
run: 'pnpm add --save-dev ${{ matrix.typescript-scenario}}'

- name: 'Type checking'
working-directory: ./test-types
run: |
pnpm tsc -v
pnpm tsc --noEmit

try-scenarios:
name: Tests - ${{ matrix.ember-try-scenario }}
runs-on: ubuntu-latest
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions addon/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# compiled output
/dist/
/declarations/
/tmp/

# dependencies
Expand Down
File renamed without changes.
File renamed without changes.
17 changes: 17 additions & 0 deletions addon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,23 @@ module('Acceptance | Register Page', function (hooks) {
});
```

### TypeScript and Glint

If your project uses loose-mode templates, you can merge in the template registry interface provided by ember-page-title,
```ts
// <your-app>/types/glint.d.ts
import '@glint/environment-ember-loose';
import '@glint/environment-ember-template-imports';

import type PageTitle from 'ember-page-title/template-registry';

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry extends PageTitle {
/* your local loose-mode entries here */
}
}
```

### Upgrading notes for 5.x to 6.x

- `ember-page-title` no longer requires the usage of `ember-cli-head`.
Expand Down
7 changes: 6 additions & 1 deletion addon/babel.config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"plugins": [
["@babel/plugin-transform-typescript", {
"allExtensions": true,
"allowDeclareFields": true,
"onlyRemoveTypeImports": true
}],
"@embroider/addon-dev/template-colocation-plugin",
["@babel/plugin-proposal-decorators", { "legacy": true }],
"@babel/plugin-proposal-class-properties"
]
}
}
46 changes: 34 additions & 12 deletions addon/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,39 @@
"license": "MIT",
"author": "Tim Evans <tim.c.evans@me.com>",
"exports": {
".": "./dist/index.js",
"./*": "./dist/*",
"./test-support": "./dist/test-support/index.js",
".": {
"types": "./declarations/index.d.ts",
"default": "./dist/index.js"
},
"./*": {
"types": "./declarations/*",
"default": "./dist/*"
},
"./test-support": {
"types": "./declarations/test-support/index.d.ts",
"default": "./dist/test-support/index.js"
},
"./addon-main.js": "./addon-main.js"
},
"files": [
"addon-main.js",
"dist"
"dist",
"declarations"
],
"repository": "https://github.com/ember-cli/ember-page-title",
"scripts": {
"build": "rollup --config",
"lint": "npm-run-all --aggregate-output --continue-on-error --parallel \"lint:!(fix)\"",
"lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
"lint:hbs": "ember-template-lint .",
"lint:hbs:fix": "ember-template-lint . --fix",
"build": "concurrently 'npm:build:*'",
"build:js": "rollup --config",
"build:types": "glint --declaration",
"lint": "concurrently 'npm:lint:*(!fix)' --names 'lint:'",
"lint:fix": "concurrently 'npm:lint:*:fix' --names 'fix:'",
"lint:js": "eslint . --cache",
"lint:js:fix": "eslint . --fix",
"prepublishOnly": "rollup --config",
"start": "rollup --config --watch"
"lint:types": "glint",
"prepack": "rollup --config",
"start": "concurrently 'npm:start:*'",
"start:js": "rollup --config --watch --no-watch.clearScreen",
"start:types": "glint --declaration --watch"
},
"dependencies": {
"@embroider/addon-shim": "^1.8.7"
Expand All @@ -45,9 +58,17 @@
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-decorators": "^7.23.6",
"@embroider/addon-dev": "^4.1.3",
"@glint/core": "^1.2.1",
"@glint/environment-ember-loose": "^1.2.1",
"@glint/environment-ember-template-imports": "^1.2.1",
"@glint/template": "^1.2.1",
"@rollup/plugin-babel": "^6.0.4",
"@tsconfig/ember": "^3.0.3",
"@types/rsvp": "^4.0.8",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"@typescript-eslint/parser": "^6.15.0",
"concurrently": "^8.2.2",
"ember-source": "^5.5.0",
"ember-template-lint": "^5.13.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
Expand All @@ -57,7 +78,8 @@
"eslint-plugin-prettier": "^5.1.2",
"npm-run-all": "^4.1.5",
"prettier": "^3.1.1",
"rollup": "^4.9.1"
"rollup": "^4.9.1",
"typescript": "^5.3.3"
},
"engines": {
"node": "16.* || >= 18"
Expand Down
10 changes: 2 additions & 8 deletions addon/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import babel from '@rollup/plugin-babel';
import { babel } from '@rollup/plugin-babel';
import { Addon } from '@embroider/addon-dev/rollup';

const addon = new Addon({
Expand Down Expand Up @@ -30,6 +30,7 @@ export default {
// It exists only to provide development niceties for you, like automatic
// template colocation.
babel({
extensions: ['.js', '.gjs', '.ts', '.gts'],
babelHelpers: 'bundled',
}),

Expand All @@ -38,13 +39,6 @@ export default {
// package names.
addon.dependencies(),

// Ensure that standalone .hbs files are properly integrated as Javascript.
addon.hbs(),

// addons are allowed to contain imports of .css files, which we want rollup
// to leave alone and keep in the published output.
addon.keepAssets(['**/*.css']),

// Remove leftover build artifacts when starting a new build.
addon.clean(),
],
Expand Down
41 changes: 0 additions & 41 deletions addon/src/helpers/page-title.js

This file was deleted.

63 changes: 63 additions & 0 deletions addon/src/helpers/page-title.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// @ts-nocheck
import { inject as service } from '@ember/service';
import Helper from '@ember/component/helper';
import { guidFor } from '@ember/object/internals';

import type PageTitleService from '../services/page-title.ts';
import type { PageTitleToken } from '../services/page-title.ts';

export type PageTitleHelperOptions = Pick<
PageTitleToken,
'prepend' | 'front' | 'replace' | 'separator'
>;

interface Signature {
Args: {
Positional: string[];
Named: PageTitleHelperOptions;
};
Return: void;
}

/**
* `{{pageTitle}}` helper used to set the title of the current route context.
*
* ```gjs
* import { pageTitle } from 'ember-page-title';
*
* <template>
* {{pageTitle "the text to set the tab's title to"}}
* {{pageTitle \@model.post.title}}
* </template>
* ```
*/
export default class PageTitle extends Helper<Signature> {
@service('page-title') declare tokens: PageTitleService;

get tokenId(): string {
return guidFor(this);
}

constructor() {
super(...arguments);
this.tokens.push({ id: this.tokenId });
}

compute(params, _hash) {
let hash = {
..._hash,
id: this.tokenId,
title: params.join(''),
};

this.tokens.push(hash);
this.tokens.scheduleTitleUpdate();
return '';
}

willDestroy() {
super.willDestroy();
this.tokens.remove(this.tokenId);
this.tokens.scheduleTitleUpdate();
}
}
1 change: 0 additions & 1 deletion addon/src/index.js

This file was deleted.

1 change: 1 addition & 0 deletions addon/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as pageTitle } from './helpers/page-title.ts';
Original file line number Diff line number Diff line change
@@ -1,27 +1,49 @@
// @ts-nocheck
import { getOwner } from '@ember/application';
import { scheduleOnce } from '@ember/runloop';
import Service, { inject as service } from '@ember/service';
import { isEmpty } from '@ember/utils';
import { assert } from '@ember/debug';
import type RouterService from '@ember/routing/router-service';

let isFastBoot = typeof FastBoot !== 'undefined';

const RouterEvent = {
ROUTE_DID_CHANGE: 'routeDidChange',
};
} as const;

interface PageTitleConfig {
/** The default separator to use between tokens. */
separator?: string;

/** The default prepend value to use. */
prepend?: boolean;

/** The default replace value to use. */
replace?: boolean | null;
}

export interface PageTitleToken extends PageTitleConfig {
id: string;
title?: string;
separator?: string;
prepend?: boolean;
replace?: boolean;
front?: unknown;
previous?: PageTitleToken | null;
next?: PageTitleToken | null;
}

/**
@class page-title
@extends Ember.Service
*/
export default class PageTitleService extends Service {
@service('router')
router;
@service('router') declare router: RouterService;

// in fastboot context "document" is instance of
// ember-fastboot/simple-dom document
@service('-document')
document;
@service('-document') declare document: Document;

tokens = [];

Expand Down
13 changes: 13 additions & 0 deletions addon/src/template-registry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { default as pageTitle } from './helpers/page-title.ts';

export default interface Registry {
/**
* `{{page-title}}` helper used to set the title of the current route context
*
* ```hbs
* {{page-title "the text to set the tab's title to"}}
* {{page-title \@model.post.title}}
* ```
*/
'page-title': typeof pageTitle;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
// Testem appends progress to the title...
// and there's no way to stop this at the moment

export function getPageTitle(doc) {
export function getPageTitle(doc: Document) {
// In Fastboot context we get 2 title elements if we don't remove one from app/index.html
// In real world applications, it is mandatory to remove <title> from app/index.html
// We are keeping both for sake for testing browser and fastboot scenarios
let element = [
...(doc || window.document).querySelectorAll('head title'),
].pop();
return element && element.innerText.trim().replace(/^\(\d+\/\d+\)/, '');

return (
element &&
element instanceof HTMLTitleElement &&
element.innerText.trim().replace(/^\(\d+\/\d+\)/, '')
);
}
1 change: 0 additions & 1 deletion addon/src/test-support/index.js

This file was deleted.

1 change: 1 addition & 0 deletions addon/src/test-support/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { getPageTitle } from './get-page-title.ts';
Loading
Loading