Notes.php

<?php

namespace Tlf\Scrawl\Extension;

/**
 * Literally does nothing except the constructor and $scrawl property. Just a base class to save boilerplate on the interface
 *
 * @NOTE this notes extension should be updated to handle TODOs as well!
 */
class Notes extends \Tlf\Scrawl\DoNothingExtension {

    /**
     * notes: <string rel_file_path, array notes_within_file>
     * notes_within_file: <int index, array note>
     * note: ['file'=>string, 'line_num'=>int, 'line'=>string]. line is trimmed
     */
    protected array $notes = [];

    /**
     * Record each @NOTE line with it's file path & line number information
     *
     * Called when an individual file is finished being processed
     *
     * @param $path absolute path to the file
     * @param $relPath relative path to the file
     * @param $file_content the content of the file
     * @param $file_exports array of all items exported from just this file
     */
    public function scan_file_processed(string $path, string $relPath, string $file_content, array $file_exports) {
        $lines = explode("\n", str_replace("\r\n", "\n", $file_content));
        $num_notes = 0;
        foreach ($lines as $index=>$text){
            $pos = $pos=stripos($text, "@NOTE");
            if ($pos===false){
                continue;
            }

            $note_text = trim(substr($text,$pos+5));
            $before_note = trim(substr($text,0,$pos));

            // @NOTE next line lists 'comment-characters' that are allowed prior to an @NOTE
            $has_non_comment_character = preg_match('/[^\/*#%"]/',$before_note);

            if ($has_non_comment_character){
                $this->scrawl->warn("Ignore @NOTE", "Line $index of $relPath");
                continue;
            }
            

            $num_notes++;
            $this->notes[$relPath][] = [
                'file' => $relPath,
                'line_num' => $index+1,
                'line' => $note_text,
            ];
        }

        if ($num_notes > 0){
            $this->scrawl->good("@NOTE", "$num_notes notes in '$relPath'",);
        }

    }

    /**
     * Write the Notes.md file
     *
     * Called when all files are finished being processed
     *
     * @param $code_files array of all files that were scanned and processed
     * @param $all_exports array of all exports found in the scanned files
     */
    public function scan_filelist_processed(array $code_files, array $all_exports){

        // @NOTE This section outputs Notes.md & contains the explainer text
        $h = "# Notes in this project's code";
        $h.= "\nNotes are marked in code by writing `@NOTE`. Everything on the line after it is captured.";
        $h.= "\n[line number] Trimmed Text of the line";

        foreach ($this->notes as $file=>$notes_within_file){
            $h.="\n\n## Notes for ".$file;
            $urlPath = $file;
            if ($urlPath[0]!='/')$urlPath = '/'.$urlPath;
            $h.="\n[Docs](/api$urlPath.md)";
            $h.="\n[Source Code]($urlPath)";
            $h.="\n";

            foreach ($notes_within_file as $note){
                $h.="\n- [".$note['line_num'].'] '.$note['line'];
            }

        }


        $this->scrawl->write_doc("Notes.md", $h);

    }

}