import re src = open('App/sims/klima/game-2d.html', 'r', encoding='utf-8').read() scripts = list(re.finditer(r']*src=)[^>]*>(.+?)', src, re.DOTALL)) print('scripts:', len(scripts)) # Only 1 script m = scripts[0] start_char = m.start(1) js = m.group(1) # Determine line offset in source prefix = src[:start_char] base_line = prefix.count('\n') + 1 print('base line:', base_line) js = re.sub(r'/\*.*?\*/', '', js, flags=re.DOTALL) BACKSLASH = chr(92) out = [] line_map = [] # map cleaned-index -> line i = 0 n = len(js) lineno = 0 while i < n: c = js[i] if c == '/' and i + 1 < n and js[i+1] == '/': while i < n and js[i] != '\n': i += 1 continue if c in ('"', "'", '`'): quote = c i += 1 while i < n: if js[i] == BACKSLASH: i += 2 continue if js[i] == '\n': lineno += 1 if js[i] == quote: i += 1 break i += 1 continue if c == '\n': lineno += 1 out.append(c) line_map.append(lineno) i += 1 code = ''.join(out) # Track brace pairs; identify orphan `{` at the end (scope gain > loss by 1) stack = [] # each entry: (line_in_script, idx) for idx, ch in enumerate(code): ln = line_map[idx] if ch == '{': stack.append((ln, idx)) elif ch == '}': if stack: stack.pop() else: print('Unmatched } at script line', ln, '= file line', base_line + ln) if stack: # orphan open braces for (ln, idx) in stack[-5:]: file_line = base_line + ln ctx = code[max(0,idx-60):idx+60] print('Orphan {{ at script line', ln, '= file line', file_line) print(' ctx:', repr(ctx))