@platformos/platformos-common 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/documents-locator/DocumentsLocator.d.ts +2 -2
- package/dist/documents-locator/DocumentsLocator.js +9 -14
- package/dist/documents-locator/DocumentsLocator.js.map +1 -1
- package/dist/frontmatter.d.ts +75 -0
- package/dist/frontmatter.js +487 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/path-utils.d.ts +34 -0
- package/dist/path-utils.js +40 -0
- package/dist/path-utils.js.map +1 -1
- package/dist/route-table/RouteTable.d.ts +26 -0
- package/dist/route-table/RouteTable.js +18 -1
- package/dist/route-table/RouteTable.js.map +1 -1
- package/dist/route-table/index.d.ts +1 -1
- package/dist/route-table/index.js +2 -1
- package/dist/route-table/index.js.map +1 -1
- package/dist/translation-provider/TranslationProvider.d.ts +10 -1
- package/dist/translation-provider/TranslationProvider.js +32 -8
- package/dist/translation-provider/TranslationProvider.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/documents-locator/DocumentsLocator.ts +10 -21
- package/src/frontmatter.ts +533 -0
- package/src/index.ts +1 -0
- package/src/path-utils.ts +55 -0
- package/src/route-table/RouteTable.ts +19 -2
- package/src/route-table/index.ts +1 -1
- package/src/translation-provider/TranslationProvider.ts +37 -15
|
@@ -16,7 +16,9 @@ function extractFrontmatter(source: string): PageFrontmatter | null {
|
|
|
16
16
|
const trimmed = source.trimStart();
|
|
17
17
|
if (!trimmed.startsWith('---')) return null;
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
// Search for the closing delimiter as `\n---` so we don't accidentally match
|
|
20
|
+
// a `---` sequence that appears inside a YAML value (e.g. `slug: my---slug`).
|
|
21
|
+
const end = trimmed.indexOf('\n---', 3);
|
|
20
22
|
if (end === -1) return null;
|
|
21
23
|
|
|
22
24
|
const yamlBlock = trimmed.slice(3, end).trim();
|
|
@@ -48,7 +50,7 @@ function extractFrontmatter(source: string): PageFrontmatter | null {
|
|
|
48
50
|
* file:///project/app/views/pages/about.html.liquid -> about.html.liquid
|
|
49
51
|
* file:///project/modules/admin/public/views/pages/dashboard.html.liquid -> dashboard.html.liquid
|
|
50
52
|
*/
|
|
51
|
-
function extractRelativePagePath(uri: string): string | null {
|
|
53
|
+
export function extractRelativePagePath(uri: string): string | null {
|
|
52
54
|
const patterns = [
|
|
53
55
|
// App-level pages: app/views/pages/ or marketplace_builder/pages/
|
|
54
56
|
/\/(app|marketplace_builder)\/(views\/pages|pages)\//,
|
|
@@ -187,6 +189,21 @@ export class RouteTable {
|
|
|
187
189
|
return this._built;
|
|
188
190
|
}
|
|
189
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Populate the route table from an in-memory collection of URI → content
|
|
194
|
+
* pairs, bypassing the filesystem entirely. Useful for warming the table
|
|
195
|
+
* from a DocumentManager without a full disk scan on startup.
|
|
196
|
+
*
|
|
197
|
+
* Only page URIs are registered; non-page URIs are silently skipped.
|
|
198
|
+
*/
|
|
199
|
+
buildFromEntries(entries: Iterable<[uri: string, content: string]>): void {
|
|
200
|
+
this.routes.clear();
|
|
201
|
+
for (const [uri, content] of entries) {
|
|
202
|
+
this.addPageFromContent(uri, content);
|
|
203
|
+
}
|
|
204
|
+
this._built = true;
|
|
205
|
+
}
|
|
206
|
+
|
|
190
207
|
async build(rootUri: URI): Promise<void> {
|
|
191
208
|
this.routes.clear();
|
|
192
209
|
|
package/src/route-table/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { RouteTable } from './RouteTable';
|
|
1
|
+
export { RouteTable, extractRelativePagePath } from './RouteTable';
|
|
2
2
|
export { slugFromFilePath, formatFromFilePath, KNOWN_FORMATS } from './slugFromFilePath';
|
|
3
3
|
export { parseSlug, calculatePrecedence } from './parseSlug';
|
|
4
4
|
export type { RouteEntry, RouteSegment } from './types';
|
|
@@ -1,14 +1,34 @@
|
|
|
1
1
|
import { AbstractFileSystem, FileType } from '../AbstractFileSystem';
|
|
2
|
+
import { parseModulePrefix } from '../path-utils';
|
|
2
3
|
import { URI, Utils } from 'vscode-uri';
|
|
3
4
|
import yaml from 'js-yaml';
|
|
4
5
|
|
|
5
|
-
type ModuleKeyInfo =
|
|
6
|
-
| { isModule: false; key: string }
|
|
7
|
-
| { isModule: true; moduleName: string; key: string };
|
|
8
|
-
|
|
9
6
|
export class TranslationProvider {
|
|
10
7
|
constructor(private readonly fs: AbstractFileSystem) {}
|
|
11
8
|
|
|
9
|
+
/** Cache for filesystem-only translation loads (bypassed when contentOverride is set). */
|
|
10
|
+
private translationsCache = new Map<string, Record<string, any>>();
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Invalidate cached translations. Call after any translation file is written
|
|
14
|
+
* to disk so subsequent calls re-read from the filesystem.
|
|
15
|
+
*
|
|
16
|
+
* Omitting `uri` clears the entire cache.
|
|
17
|
+
* Passing a `uri` removes only the entries whose base directory contains that file.
|
|
18
|
+
*/
|
|
19
|
+
clearTranslationsCache(uri?: string): void {
|
|
20
|
+
if (!uri) {
|
|
21
|
+
this.translationsCache.clear();
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
for (const key of this.translationsCache.keys()) {
|
|
25
|
+
const baseUri = key.slice(0, key.lastIndexOf(':'));
|
|
26
|
+
if (uri.startsWith(baseUri)) {
|
|
27
|
+
this.translationsCache.delete(key);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
12
32
|
private async isFile(path: string): Promise<boolean> {
|
|
13
33
|
try {
|
|
14
34
|
return (await this.fs.stat(path)).type === FileType.File;
|
|
@@ -42,16 +62,6 @@ export class TranslationProvider {
|
|
|
42
62
|
return true;
|
|
43
63
|
}
|
|
44
64
|
|
|
45
|
-
private parseModuleKey(translationKey: string): ModuleKeyInfo {
|
|
46
|
-
if (!translationKey.startsWith('modules/')) {
|
|
47
|
-
return { isModule: false, key: translationKey };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const [, moduleName, key] = translationKey.split('/', 3);
|
|
51
|
-
|
|
52
|
-
return key ? { isModule: true, moduleName, key } : { isModule: false, key: translationKey };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
65
|
static getSearchPaths(moduleName?: string): string[] {
|
|
56
66
|
if (!moduleName) {
|
|
57
67
|
return ['app/translations'];
|
|
@@ -70,7 +80,7 @@ export class TranslationProvider {
|
|
|
70
80
|
translationKey: string,
|
|
71
81
|
defaultLocale: string,
|
|
72
82
|
): Promise<[string | undefined, string | undefined]> {
|
|
73
|
-
const parsed =
|
|
83
|
+
const parsed = parseModulePrefix(translationKey);
|
|
74
84
|
|
|
75
85
|
if (!parsed.key) {
|
|
76
86
|
return [undefined, undefined];
|
|
@@ -129,6 +139,14 @@ export class TranslationProvider {
|
|
|
129
139
|
locale: string,
|
|
130
140
|
contentOverride?: (uri: string) => string | undefined,
|
|
131
141
|
): Promise<Record<string, any>> {
|
|
142
|
+
const cacheKey = `${translationBaseUri.toString()}:${locale}`;
|
|
143
|
+
|
|
144
|
+
// Return cached result when the caller has no editor overrides (e.g. linter/CI).
|
|
145
|
+
// Skip cache when contentOverride is set — unsaved buffer content may differ from disk.
|
|
146
|
+
if (!contentOverride && this.translationsCache.has(cacheKey)) {
|
|
147
|
+
return this.translationsCache.get(cacheKey)!;
|
|
148
|
+
}
|
|
149
|
+
|
|
132
150
|
const merged: Record<string, any> = {};
|
|
133
151
|
|
|
134
152
|
const read = async (uri: string): Promise<string | undefined> => {
|
|
@@ -158,6 +176,10 @@ export class TranslationProvider {
|
|
|
158
176
|
}
|
|
159
177
|
}
|
|
160
178
|
|
|
179
|
+
if (!contentOverride) {
|
|
180
|
+
this.translationsCache.set(cacheKey, merged);
|
|
181
|
+
}
|
|
182
|
+
|
|
161
183
|
return merged;
|
|
162
184
|
}
|
|
163
185
|
|