ts-version

- ts version vom link_collector hinzugefügt
This commit is contained in:
Adam Skotarczak 2025-05-26 14:58:30 +02:00
parent 42afb2769a
commit d8afdfabc3
4 changed files with 306 additions and 0 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
.vscode/
node_modules/

74
package-lock.json generated Normal file
View File

@ -0,0 +1,74 @@
{
"name": "adminslog",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"fs": "^0.0.1-security",
"path": "^0.12.7",
"process": "^0.11.10"
},
"devDependencies": {
"@types/node": "^22.15.21"
}
},
"node_modules/@types/node": {
"version": "22.15.21",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz",
"integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/fs": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
"integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==",
"license": "ISC"
},
"node_modules/inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
"license": "ISC"
},
"node_modules/path": {
"version": "0.12.7",
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
"integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==",
"license": "MIT",
"dependencies": {
"process": "^0.11.1",
"util": "^0.10.3"
}
},
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"license": "MIT",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true,
"license": "MIT"
},
"node_modules/util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
"license": "MIT",
"dependencies": {
"inherits": "2.0.3"
}
}
}
}

10
package.json Normal file
View File

@ -0,0 +1,10 @@
{
"dependencies": {
"fs": "^0.0.1-security",
"path": "^0.12.7",
"process": "^0.11.10"
},
"devDependencies": {
"@types/node": "^22.15.21"
}
}

View File

@ -0,0 +1,220 @@
#!/usr/bin/env ts-node
import * as fs from 'fs';
import * as path from 'path';
import * as process from 'process';
type Config = {
root_dirs?: string[];
output_file?: string;
processed_log?: string;
extensions?: string[];
};
type Args = {
scan: string[] | null;
ignore: string[];
reset: boolean;
hilfe: boolean;
};
class ScriptInfo {
static dir(): string {
return path.dirname(__filename);
}
static cwd(): string {
return process.cwd();
}
}
class ConfigLoader {
static load(filename = 'config.jsonc'): Config {
const configPath = path.join(ScriptInfo.dir(), filename);
if (!fs.existsSync(configPath)) {
console.error(` ⚠ Konfigurationsdatei nicht gefunden: ${configPath}`);
process.exit(1);
}
const raw = fs.readFileSync(configPath, 'utf8');
const clean = raw
.split('\n')
.filter(line => !line.trim().startsWith('//'))
.join('');
return JSON.parse(clean);
}
}
class ArgParser {
static parse(): Args {
const argv = process.argv.slice(2);
const result: Args = { scan: null, ignore: [], reset: false, hilfe: false };
while (argv.length) {
const arg = argv.shift();
if (!arg) break;
if (arg === '-h' || arg === '--hilfe') {
result.hilfe = true;
} else if (arg === '--reset') {
result.reset = true;
} else if ((arg === '-s' || arg === '--scan') && argv.length) {
result.scan = argv.shift()!.split(',').map(x => x.trim()).filter(Boolean);
} else if ((arg === '-x' || arg === '--ignore') && argv.length) {
result.ignore = argv.shift()!.split(',').map(x => x.trim()).filter(Boolean);
} else {
console.warn(` ⚠ Unbekannter Parameter: ${arg}`);
result.hilfe = true;
break;
}
}
return result;
}
static showHelp(): void {
console.log(`
(C) 2025 - Adam Skotarczak (ionivation.com)
🛈 Tool das Verzeichnisse nach Markdown-Dateien durchsucht und diese an eine definierte Liste anhängt als Markdown-Link.
Verwendung: ts-node link_collector.ts [OPTIONEN]
-s, --scan Kommagetrennte Liste von Verzeichnissen zum Durchsuchen (relativ zum Aufrufpfad)
-x, --ignore Kommagetrennte Liste von Verzeichnissen, die ignoriert werden sollen
--reset Löscht das Logfile 'processed.log' und beendet sich
-h, --hilfe Zeigt diese Hilfe
Beispiel:
ts-node link_collector.ts -s docs,notes -x "docs/alt"
`);
}
}
class FileScanner {
static *find(rootDirs: string[], ignoreDirs: string[], extensions: string[]): Generator<string> {
for (const root of rootDirs) {
const absRoot = path.resolve(root);
const stack = [absRoot];
while (stack.length) {
const current = stack.pop()!;
const rel = path.relative(ScriptInfo.cwd(), current).replace(/\\/g, '/');
if (ignoreDirs.some(ignored => rel.startsWith(ignored))) continue;
const entries = fs.readdirSync(current, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(current, entry.name);
if (entry.isDirectory()) {
stack.push(fullPath);
} else if (extensions.some(ext => entry.name.endsWith(ext))) {
yield fullPath;
}
}
}
}
}
}
class TitleExtractor {
static extract(filepath: string): string {
try {
const content = fs.readFileSync(filepath, 'utf8');
for (const line of content.split('\n')) {
if (line.trim().startsWith('#')) {
return line.replace(/^#+/, '').trim();
}
}
} catch (e) {
console.error(`⚠ Fehler beim Lesen von ${filepath}: ${e}`);
}
return path.basename(filepath, path.extname(filepath));
}
}
class ProcessedLog {
private readonly logPath: string;
private entries: Set<string>;
constructor(filename: string) {
this.logPath = path.join(ScriptInfo.dir(), filename);
this.entries = new Set<string>();
this.load();
}
private load() {
if (!fs.existsSync(this.logPath)) return;
const lines = fs.readFileSync(this.logPath, 'utf8').split('\n').map(x => x.trim()).filter(Boolean);
this.entries = new Set(lines.map(p => p.replace(/\\/g, '/')));
}
has(posixPath: string): boolean {
return this.entries.has(posixPath);
}
update(newPaths: string[]): void {
const content = newPaths.map(p => p.replace(/\\/g, '/')).join('\n') + '\n';
fs.appendFileSync(this.logPath, content, 'utf8');
}
reset(): void {
if (fs.existsSync(this.logPath)) {
fs.unlinkSync(this.logPath);
console.log('🧹 Logfile gelöscht:', this.logPath);
} else {
console.log(' Logfile existierte nicht:', this.logPath);
}
}
}
class MarkdownAppender {
static append(outputFile: string, links: string[]): void {
const content = links.join('\n') + '\n';
fs.appendFileSync(outputFile, content, 'utf8');
}
}
// Einstiegspunkt
function main() {
const config = ConfigLoader.load();
const args = ArgParser.parse();
if (args.hilfe) {
ArgParser.showHelp();
return;
}
const log = new ProcessedLog(config.processed_log || 'processed.log');
if (args.reset) {
log.reset();
return;
}
const cwd = ScriptInfo.cwd();
const outputFile = path.resolve(cwd, config.output_file || 'output.md');
const rootDirs = (args.scan || config.root_dirs || []).map(d => path.resolve(d));
const ignoreDirs = (args.ignore || []).map(d => path.relative(cwd, path.resolve(d)).replace(/\\/g, '/'));
const extensions = config.extensions || ['.md'];
const newLinks: string[] = [];
const newProcessed: string[] = [];
for (const absPath of FileScanner.find(rootDirs, ignoreDirs, extensions)) {
const relPath = path.relative(cwd, absPath).replace(/\\/g, '/');
if (path.resolve(absPath) === outputFile || log.has(relPath)) continue;
const title = TitleExtractor.extract(absPath);
newLinks.push(`- [${title}](${relPath})`);
newProcessed.push(relPath);
}
if (newLinks.length > 0) {
MarkdownAppender.append(outputFile, newLinks);
log.update(newProcessed);
console.log(`${newLinks.length} neue Links hinzugefügt.`);
} else {
console.log(' Keine neuen Dateien gefunden.');
}
}
main();