function collectSnippets()

in scripts/separate-snippets.ts [152:225]


function collectSnippets(filePath: string): SnippetsConfig {
  const fileContents = fs.readFileSync(filePath).toString();
  const lines = fileContents.split("\n");

  const config: SnippetsConfig = {
    enabled: false,
    suffix: DEFAULT_SUFFIX,
    map: {},
  };

  // If a file does not have '// [SNIPPETS_SEPARATION enabled]' in it then 
  // we don't process it for this script.
  config.enabled = lines.some((l) => !!l.match(RE_SNIPPETS_SEPARATION));
  if (!config.enabled) {
    return config;
  }

  // If the file contains '// [SNIPPETS_SUFFIX _banana]' we use _banana (or whatever)
  // as the suffix. Otherwise we default to _modular.
  const suffixLine = lines.find((l) => !!l.match(RE_SNIPPETS_SUFFIX));
  if (suffixLine) {
    const m = suffixLine.match(RE_SNIPPETS_SUFFIX);

    if (m && m[1]) {
      config.suffix = m[1];
    }
  }

  // A temporary array holding the names of snippets we're currently within.
  // This allows for handling nested snippets.
  let inSnippetNames: string[] = [];

  for (const line of lines) {
    const startMatch = line.match(RE_START_SNIPPET);
    const endMatch = line.match(RE_END_SNIPPET);

    if (startMatch) {
      // When we find a new [START foo] tag we are now inside snippet 'foo'.
      // Until we find an [END foo] tag. All lines we see between now and then
      // are part of the snippet content.
      const snippetName = startMatch[1];
      if (config.map[snippetName] !== undefined) {
        throw new Error(`Detected more than one snippet with the tag ${snippetName}!`);
      }

      config.map[snippetName] = [line];
      inSnippetNames.push(snippetName);
    } else if (endMatch) {
      // When we find a new [END foo] tag we are now exiting snippet 'foo'.
      const snippetName = endMatch[1];

      // If we were not aware that we were inside this snippet (no previous START)
      // then we hard throw.
      if (!inSnippetNames.includes(snippetName)) {
        throw new Error(
          `Unrecognized END tag ${snippetName} in ${filePath}.`
        );
      }

      // Collect this line as the final line of the snippet and then
      // remove this snippet name from the list we're tracking.
      config.map[snippetName].push(line);
      inSnippetNames.splice(inSnippetNames.indexOf(snippetName), 1);
    } else if (inSnippetNames.length > 0) {
      // Any line that is not START or END is appended to the list of
      // lines for all the snippets we're currently tracking.
      for (const snippetName of inSnippetNames) {
        config.map[snippetName].push(line);
      }
    }
  }

  return config;
}