ts-version
- ts version vom link_collector hinzugefügt
This commit is contained in:
parent
42afb2769a
commit
d8afdfabc3
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
||||
.vscode/
|
||||
|
||||
node_modules/
|
||||
|
74
package-lock.json
generated
Normal file
74
package-lock.json
generated
Normal 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
10
package.json
Normal 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"
|
||||
}
|
||||
}
|
220
tools/collector/link_collector.ts
Normal file
220
tools/collector/link_collector.ts
Normal 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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user