''' Generate a definition file with a global namespace from a typescript module definition file ''' import os import pathlib import re import argparse parser = parser = argparse.ArgumentParser(description='Generate a definition file with a global namespace from a typescript module definition file') parser.add_argument('namespace', help='Namespace used in the global script. (example: Three.js use THREE as its namespace)') parser.add_argument('output_filename', help='Output d.ts definition file. (example: three.d.ts)') args = parser.parse_args() output_filename = args.output_filename namespace = args.namespace import_pattern = re.compile( r"import(?:[\"'\s]*([\w*{}\n\r\t, ]+)from\s*)?[\"'\s].*([@\w_-]+)[\"'\s].*;" ) export_pattern = re.compile( r"export ([*] from [\"'\s].*[\"'\s]|{.*}(?: from [\"'\s].*[\"'\s])?);" ) filter_directories = ["./Enums", "./Interfaces"] def main(): ''' Entry point function ''' with open(output_filename, 'w') as output_file: output_file.write(('declare namespace {} {{\n'.format(namespace))) for root, subdirs, files in os.walk('./'): if root not in filter_directories: continue print('--\nroot = ' + root) for subdir in subdirs: print('\t- subdirectory ' + subdir) for filename in files: if filename == 'output.d.ts': continue if filename == 'my-directory-list.txt': os.remove(os.path.join(root, filename)) continue suffixes = pathlib.Path(filename).suffixes if (suffixes != ['.d', '.ts']): continue file_path = os.path.join(root, filename) file_path = file_path.replace('\\', '/') print('\t- file %s (full path: %s)' % (filename, file_path)) with open(file_path, 'r') as cur_file: f_content = cur_file.read() # removes imports # see https://gist.github.com/manekinekko/7e58a17bc62a9be47172 f_content = import_pattern.sub('', f_content) # Replace 'export { my_class as synonym };' # => 'class synonym extend my_class {}' f_content = re.sub( r"export ({ ([A-Z].*) as ([A-Z].*) });", "export class \\g<3> extends \\g<2> {}", f_content, 0, re.MULTILINE ) # Replace 'export declare class' => 'export class' f_content = re.sub(r"export (declare) class", 'export class', f_content, 0, re.MULTILINE) f_content = re.sub(r"export (declare) enum", 'export enum', f_content, 0, re.MULTILINE) f_content = re.sub(r"export (declare) function", 'export function', f_content, 0, re.MULTILINE) f_content = re.sub(r"export (declare) type", 'export type', f_content, 0, re.MULTILINE) # Replace 'export { my_func as synonym }' => 'export function synonym = my_func' # Replace 'export default class' => 'export class' f_content = re.sub(r"(export) default", "\\1", f_content, 0, re.MULTILINE) # Replace other exports : 'export { .* } from '.*';' and 'export [*] from '.*'; f_content = export_pattern.sub('', f_content) # Specific to your module f_content = re.sub('export as namespace {};'.format(namespace), '', f_content) output_file.write(f_content) output_file.write('\n') output_file.write(('}\n')) main()