11import fs from "fs" ;
22import path from "path" ;
3+ import { spawnSync } from "child_process" ;
4+ import { fileURLToPath } from "url" ;
35
46function readJson ( filePath ) {
57 return JSON . parse ( fs . readFileSync ( filePath , "utf8" ) ) ;
@@ -29,7 +31,7 @@ function resolveSnippetPath(snippet, locale) {
2931 return fs . existsSync ( localized ) ? localized : path . join ( base , snippet ) ;
3032}
3133
32- function toAscii ( text ) {
34+ export function toAscii ( text ) {
3335 return text
3436 . replace ( / \r \n / g, "\n" )
3537 . replace ( / \uFEFF / g, "" )
@@ -41,47 +43,97 @@ function toAscii(text) {
4143 . replace ( / [ – — ] / g, "-" ) ;
4244}
4345
44- function printUsage ( ) {
45- console . error (
46- "Usage: node scripts/print-method-snippet.js <resource-id> [locale] [--ascii]" ,
46+ export function getActiveWindowsCodePage ( ) {
47+ const override = process . env . APIOPS_WINDOWS_CODEPAGE ;
48+ if ( override ) {
49+ return Number . parseInt ( override , 10 ) ;
50+ }
51+
52+ const result = spawnSync (
53+ process . env . ComSpec || "cmd.exe" ,
54+ [ "/d" , "/s" , "/c" , "chcp" ] ,
55+ {
56+ encoding : "utf8" ,
57+ windowsHide : true ,
58+ } ,
4759 ) ;
60+
61+ const output = `${ result . stdout || "" } \n${ result . stderr || "" } ` ;
62+ const match = output . match ( / ( \d { 3 , 5 } ) / ) ;
63+ return match ? Number . parseInt ( match [ 1 ] , 10 ) : null ;
4864}
4965
50- const args = process . argv . slice ( 2 ) ;
51- const ascii = args . includes ( "--ascii" ) ;
52- const positional = args . filter ( ( arg ) => arg !== "--ascii" ) ;
53- const resourceId = positional [ 0 ] ;
54- const locale = positional [ 1 ] || "en" ;
66+ export function shouldUseAsciiFallback ( forceAscii , forceUnicode ) {
67+ if ( forceAscii ) {
68+ return true ;
69+ }
5570
56- if ( ! resourceId ) {
57- printUsage ( ) ;
58- process . exit ( 1 ) ;
59- }
71+ if ( forceUnicode ) {
72+ return false ;
73+ }
6074
61- const resources = readJson ( resolveMethodFile ( "resources.json" ) ) . resources ;
62- const resource = resources . find ( ( entry ) => entry . id === resourceId ) ;
75+ const isWindows = process . platform === "win32" || process . env . APIOPS_FORCE_WINDOWS === "1" ;
76+ if ( ! isWindows ) {
77+ return false ;
78+ }
6379
64- if ( ! resource ) {
65- console . error ( `Unknown resource id: ${ resourceId } ` ) ;
66- process . exit ( 1 ) ;
80+ const codePage = getActiveWindowsCodePage ( ) ;
81+ return codePage !== null && codePage !== 65001 ;
6782}
6883
69- if ( ! resource . snippet ) {
70- console . error ( `Resource ${ resourceId } does not define a snippet` ) ;
71- process . exit ( 1 ) ;
84+ function printUsage ( ) {
85+ console . error (
86+ "Usage: node scripts/print-method-snippet.js <resource-id> [locale] [--ascii] [--unicode]" ,
87+ ) ;
7288}
7389
74- const snippetPath = resolveSnippetPath ( resource . snippet , locale ) ;
90+ export function renderSnippet ( resourceId , locale = "en" , options = { } ) {
91+ const resources = readJson ( resolveMethodFile ( "resources.json" ) ) . resources ;
92+ const resource = resources . find ( ( entry ) => entry . id === resourceId ) ;
93+
94+ if ( ! resource ) {
95+ throw new Error ( `Unknown resource id: ${ resourceId } ` ) ;
96+ }
97+
98+ if ( ! resource . snippet ) {
99+ throw new Error ( `Resource ${ resourceId } does not define a snippet` ) ;
100+ }
101+
102+ const snippetPath = resolveSnippetPath ( resource . snippet , locale ) ;
103+ if ( ! fs . existsSync ( snippetPath ) ) {
104+ throw new Error ( `Snippet not found: ${ snippetPath } ` ) ;
105+ }
75106
76- if ( ! fs . existsSync ( snippetPath ) ) {
77- console . error ( `Snippet not found: ${ snippetPath } ` ) ;
78- process . exit ( 1 ) ;
107+ let content = fs . readFileSync ( snippetPath , "utf8" ) ;
108+ if ( shouldUseAsciiFallback ( options . forceAscii , options . forceUnicode ) ) {
109+ content = toAscii ( content ) ;
110+ }
111+
112+ return content ;
79113}
80114
81- let content = fs . readFileSync ( snippetPath , "utf8" ) ;
115+ function main ( ) {
116+ const args = process . argv . slice ( 2 ) ;
117+ const forceAscii = args . includes ( "--ascii" ) ;
118+ const forceUnicode = args . includes ( "--unicode" ) ;
119+ const positional = args . filter ( ( arg ) => arg !== "--ascii" && arg !== "--unicode" ) ;
120+ const resourceId = positional [ 0 ] ;
121+ const locale = positional [ 1 ] || "en" ;
122+
123+ if ( ! resourceId ) {
124+ printUsage ( ) ;
125+ process . exit ( 1 ) ;
126+ }
82127
83- if ( ascii ) {
84- content = toAscii ( content ) ;
128+ try {
129+ const content = renderSnippet ( resourceId , locale , { forceAscii, forceUnicode } ) ;
130+ process . stdout . write ( content , "utf8" ) ;
131+ } catch ( error ) {
132+ console . error ( error instanceof Error ? error . message : error ) ;
133+ process . exit ( 1 ) ;
134+ }
85135}
86136
87- process . stdout . write ( content ) ;
137+ if ( process . argv [ 1 ] && path . resolve ( process . argv [ 1 ] ) === fileURLToPath ( import . meta. url ) ) {
138+ main ( ) ;
139+ }
0 commit comments