Skip to content

feat(ts-content-mapper): add a TypeScript content mapper for .astro files - #17835

Merged
Princesseuh merged 8 commits into
mainfrom
feat/ts-content-mapper
Sep 17, 2026
Merged

Princesseuh merged 8 commits into
mainfrom
feat/ts-content-mapper

Conversation

@Princesseuh

@Princesseuh Princesseuh commented Aug 26, 2026 •

Copy link
Copy Markdown
Member

Changes

This PR adds the long-awaited TypeScript 7 content mapper for Astro, waouw!

Users of TS >=7.1 are able to install this package, configure it in their tsconfig.json, run tsc normally (well, with a flag for now) and get their .astro files type checked as if they were just normal TS files. This also support emitting and editor features.

For the editor part, there's some work still needed in the language server and VS Code extension to make it register the content mapper for users automatically and not have both the old pipeline and new one running at once, see #17852

Testing

Added tests for the mappings existing and being generated correctly.

We unfortunately can't add full E2E tests for this until TypeScript 7.1 is fully out and we're migrated because otherwise you get multiple TS versions and everything breaks, or at least that was my experience. Couldn't figure it out.

Documentation

Probably needs a page or mention somewhere, but since this is only for nightly right now, I don't think it's required for this to get merged

@changeset-bot

changeset-bot Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: a2a5e37

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@Princesseuh
Princesseuh force-pushed the feat/astro2tsx-language-server branch 2 times, most recently from 21c2668 to 796841a Compare September 16, 2026 13:57
Base automatically changed from feat/astro2tsx-language-server to main September 16, 2026 13:59
@Princesseuh
Princesseuh force-pushed the feat/ts-content-mapper branch 9 times, most recently from 47915e9 to e6e7a45 Compare September 17, 2026 00:46
@Princesseuh
Princesseuh marked this pull request as ready for review September 17, 2026 00:56
Comment on lines +3 to +39
export type PositionEncoding = 'utf-8' | 'utf-16';

export interface InitializeParams {
positionEncodings: PositionEncoding[];
}

export interface InitializeResult {
positionEncoding: PositionEncoding;
diagnosticSource: string;
}

export interface TransformParams {
fileName: string;
content: string;
projectHandle: string;
}

export interface SupplementalOutput {
text: string;
extension: '.mjs' | '.mts';
mappings: ConvertToTsxResult['mappings'];
}

export interface TransformResult {
text: string;
extension: '.tsx';
mappings: ConvertToTsxResult['mappings'];
diagnostics: MapperDiagnostic[];
supplemental?: SupplementalOutput[];
}

export interface MapperDiagnostic {
messageText: string;
start: number;
length: number;
code: number;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bunch of types that I feel should be exported from TypeScript directly, but I couldn't find them and anyway, with it being just in the nightly for now we can't really depend on it even if we wanted to.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it possible to share the feedback with the TS team to see if we could depend on them once shipped?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking around it seems like this is already planned, it's just currently in some unstable modules.

import type { InitializeParams, InitializeResult } from './protocol.js';
import { transform } from './transform.js';

const POSITION_ENCODING = 'utf-16';

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -0,0 +1,27 @@
# @astrojs/ts-content-mapper

A [TypeScript content mapper](https://github.com/microsoft/TypeScript/pull/63936) for `.astro` files. It lets TypeScript 7.1+ (`tsc`) parse and type-check Astro components directly, without needing to use a different language server or CLI Tool.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's a better link for now unfortunately, when 7.1 releases I assume the blog post will talk about it.

@Princesseuh
Princesseuh force-pushed the feat/ts-content-mapper branch from 863278c to 7f363d4 Compare September 17, 2026 16:31
(script) =>
script.type === ExtractedScriptType.Inline ||
script.type === ExtractedScriptType.EventAttribute ||
script.type === ExtractedScriptType.Unknown,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is an unknown script?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's when we don't know what's inside a script, like <script type="something-unknown"></script> or <script type={dynamic}>. Fwiw this code is the same as the previous implementation with the same enums etc.


const VERBATIM = 0;
const ATOM = 1;
const DEFINITION = 1 << 3;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on using bitwise

@matthewp matthewp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

less code than I expected

@Princesseuh
Princesseuh merged commit faa2119 into main Sep 17, 2026
28 checks passed
@Princesseuh
Princesseuh deleted the feat/ts-content-mapper branch September 17, 2026 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants