Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
671 changes: 671 additions & 0 deletions README copy.md

Large diffs are not rendered by default.

676 changes: 24 additions & 652 deletions README.md

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env node
const yargs = require('yargs');
const { mdLinks } = require('./index.js');
const { countTotalAndUnique, countBrokenLinks } = require('./functions.js');
const chalk = require('chalk');

console.log(chalk.magentaBright("*************************************"));
console.log(chalk.magentaBright('Hey! :) Here is lin-md-links library!'));
console.log(chalk.magentaBright("*************************************"));

console.log(" /\\_/\\");
console.log("=( o.o )=");
console.log(" > - <");

console.log(chalk.yellow("Quick tip! If your path has inverted backslashes instead of '/',\n please enter your path within double quotes, ty! ;) \n"));


// Yargs paquete de Node.js que simplifica la tarea de manejar argumentos de línea de comandos.
//Yargs se encarga del análisis de los argumentos y opciones proporcionados por el usuario

/* process.argv: es un arreglo que contiene los argumentos
pasados al programa Node.js desde la línea de comandos.
pero yargs simplifica el uso de estos argumentos y proporciona una interfaz más conveniente. */

yargs
.usage(chalk.bold.cyanBright('md-links ./path/to/file.md -v -s'))
.command('$0', chalk.cyan('Default command'))
.option('v', {
alias: 'validate',
describe: chalk.cyan('-v to check the status of each link'),
type: 'boolean',
default: false,
})
.option('s', {
alias: 'stats',
describe: 'Show statistics about the links',
type: 'boolean',
default: false,
})
.help('h')
.alias('h', 'help')
.argv;
//se utiliza .argv para obtener un objeto que representa los argumentos y opciones proporcionados por el usuario.

const args = yargs.argv; //accedes a los args que te da el usuario
const filePath = args._[0]; //se accede al primer elemento del arreglo, para obtener la ruta que da el usuario
const options = {
validate: args.validate,
stats: args.stats,
};

if (!filePath) {
console.error(chalk.red('Error: You must provide a path.'));
process.exit(1);
}

mdLinks(filePath, options)
.then((linksWithStatus) => {
if (options.stats) {
const totalStats = `Total: ${linksWithStatus.length}`;
const uniqueStats = countTotalAndUnique(linksWithStatus);
const brokenStats = `Broken: ${countBrokenLinks(linksWithStatus)}`;
console.log(chalk.cyanBright(totalStats));
console.log(chalk.cyanBright(`Unique: ${uniqueStats.unique}`));
console.log(chalk.cyanBright(brokenStats));
}
if (options.validate) {
linksWithStatus.forEach((link) => {
const statusInfo = link.ok === 'OK' ? 'OK' : 'Fail';
console.log(
`${chalk.magenta('Text:')} ${chalk.green(link.text)}\n` +
`${chalk.magenta('href:')} ${chalk.green(link.href)}\n` +
`${chalk.magenta('File:')} ${chalk.green(link.file)}\n` +
`${chalk.magenta('Status:')} ${chalk.green(link.status)}\n` +
`${chalk.magenta('StatusInfo:')} ${chalk.green(statusInfo)}\n`
);
});
} else {
linksWithStatus.forEach((link) => {
console.log(
`${chalk.magenta('Text:')} ${chalk.green(link.text)}\n` +
`${chalk.magenta('href:')} ${chalk.green(link.href)}\n` +
`${chalk.magenta('File:')} ${chalk.green(link.file)}\n`
);
});
}
})
.catch((error) => {
console.error(error);
});


35 changes: 35 additions & 0 deletions extra.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## 3. Objetivos de aprendizaje

Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en tu proyecto. Piensa en eso al decidir tu estrategia de trabajo.

### JavaScript

- [ ] **Diferenciar entre tipos de datos primitivos y no primitivos**

- [ ] **Arrays (arreglos)**

<details><summary>Links</summary><p>

* [Arreglos](https://curriculum.laboratoria.la/es/topics/javascript/04-arrays)
* [Array - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/)
* [Array.prototype.sort() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
* [Array.prototype.forEach() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
* [Array.prototype.map() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
* [Array.prototype.filter() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
* [Array.prototype.reduce() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)
</p></details>

- [ ] **Objetos (key, value)**

<details><summary>Links</summary><p>

* [Objetos en JavaScript](https://curriculum.laboratoria.la/es/topics/javascript/05-objects/01-objects)
</p></details>

- [ ] **Uso de condicionales (if-else, switch, operador ternario, lógica booleana)**

<details><summary>Links</summary><p>

* [Estructuras condicionales y repetitivas](https://curriculum.laboratoria.la/es/topics/javascript/02-flow-control/01-conditionals-and-loops)
* [Tomando decisiones en tu código — condicionales - MDN](https://developer.mozilla.org/es/docs/Learn/JavaScript/Building_blocks/conditionals)
</p></details>
169 changes: 169 additions & 0 deletions functions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
const fs = require("fs"); //módulo se utiliza para interactuar con el sistema de archivos.
const path = require("path"); //módulo se utiliza para trabajar con rutas de archivos y directorios de manera compatible con diferentes sistemas operativos.
const axios = require('axios');


// Función para verificar si un archivo o directorio existe
function fileOrDirExists(filePath) {
return fs.existsSync(filePath);
}
//console.log("Path exists:", fileOrDirExists('./extra.md'));

// Función para convertir una ruta relativa en absoluta
function convertToAbsolute(filePath) {
return path.resolve(filePath);
}
//usa el módulo path con su método resolve
//console.log("Absolute path:", convertToAbsolute ('./extra.md'));
//console.log("Absolute path:", convertToAbsolute ('./index.js'));

// Confirmar si es un archivo .md
function isMarkdownFile(filePath) {
return path.extname(filePath) === ".md";
}
//console.log("Is markdown file:", isMarkdownFile('./extra.md'));

//const filePath = 'D:/Laboratoria/DEV008-md-links/README.md';
//const filePath = 'D:/Laboratoria/DEV008-md-links/extra.md'; //error al copiar path?


// Leer el archivo .md
//callback**
function readFileContent(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf-8', (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}


// Buscar links dentro del .md

const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;

function findLinksInMarkdown(markdownContent, filePath) {
return new Promise((resolve, reject) => {
const links = [];
let match;

while ((match = linkRegex.exec(markdownContent)) !== null) {
const [, linkText, linkUrl] = match;
links.push({
text: linkText,
href: linkUrl,
file: filePath
});
}

resolve(links);
});
}

/*
readFileContent(filePath)
.then((markdownContent) => {
return findLinksInMarkdown(markdownContent, filePath);
})
.then((links) => {
return getStatusLinks(links);
})
.then((linksWithStatus) => {
//linksWithStatus no está declarada porque se obtiene como resultado de la promesa
console.log("Links with status:", linksWithStatus);

const totalAndUnique = countTotalAndUnique(linksWithStatus);
const brokenLinkCount = countBrokenLinks(linksWithStatus);

console.log('Total Links:', totalAndUnique.total);
console.log('Unique Links:', totalAndUnique.unique);
console.log('Broken Links:', brokenLinkCount);
})

.catch((error) => {
console.error("Error:", error);
}); */



// Pedir el código status HTTP -fetch o axios
//Axios aquí

//transforma en newPromise
function getStatusLinks(linksArray) {
const promises = linksArray.map((link) => {
return axios.get(link.href)
.then((response) => {
const statusText = `${response.status}`;
const ok = response.status === 200 ? "OK" : "fail";
return { ...link, status: statusText, ok };
})
.catch((error) => {
let statusText = 'HTTP Status Code: Unknown Error';
const ok = "fail";

if (error.response) {
statusText = `${error.response.status} ${error.response.statusText}`;
}

return { ...link, status: statusText, ok };
});
});

return Promise.all(promises);
}

// Spread Syntax (...)
// eso agrega los elementos individuales al arreglo links.

//-----------------------------Here functions for stats!!!-------------------------------------
// Count total and unique links
function countTotalAndUnique(linksArray) {
const totalLinks = linksArray.length;

//con Set NO sirve lenght, usar .size*
//Set-estructura de datos Js que representa una colección de valores únicos
const uniqueLinks = new Set(linksArray.map((link) => link.href));
return {
total: totalLinks,
unique: uniqueLinks.size,
};
}


// count broken links
function countBrokenLinks(linksArray) {
let count = 0;
for (const link of linksArray) {
if (link.ok !== 'OK') {
count++;
}
}
return count;
}
/* function countBrokenLinks(linksArray) {
return linksArray.reduce((count, link) => {
if (link.ok !== 'OK') {
count++;
}
return count;
}, 0);
} */


//Comentario para readme2

module.exports = {
fileOrDirExists,
convertToAbsolute,
isMarkdownFile,
readFileContent,
getStatusLinks,
findLinksInMarkdown,
countTotalAndUnique,
countBrokenLinks,
};
Binary file added iferror.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 60 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,60 @@
module.exports = () => {
// ...
};
const fs = require("fs");
const {
fileOrDirExists,
convertToAbsolute,
isMarkdownFile,
readFileContent,
getStatusLinks,
findLinksInMarkdown,
} = require('./functions.js');



// aquí va mdLinks
//función principal que tomará una ruta de archivo y opciones, y devolverá una promesa.
const mdLinks = (filePath, options = { validate: false, stats: false }) => new Promise((resolve, reject) => {
//const shouldValidate = options.validate;
//const shouldShowStats = options.stats;
const absolutePath = convertToAbsolute(filePath);
const pathExist = fs.existsSync(absolutePath);

if (!pathExist) {
return reject(new Error('Path does not exist' + absolutePath));
}

const isMdFile = isMarkdownFile(absolutePath);
if (!isMdFile) {
return reject(new Error('File is not a markdown!'));
}

readFileContent(filePath)
.then((markdownContent) => {
return findLinksInMarkdown(markdownContent, filePath);
})
.then((links) => {
return getStatusLinks(links);
})
.then((linksWithStatus) => {
//linksWithStatus no está declarada porque se obtiene como resultado de la promesa
resolve(linksWithStatus);
})
.catch((error) => {
// En caso de error, rechazamos la promesa
reject(error);
});
});




//..to try mdLinks promise
/* mdLinks('D:/Laboratoria/DEV008-md-links/README.md', { validate: true }).then((result) => {
console.log(result);
}).catch((error) => {
console.error(error);
}); */


module.exports = {
mdLinks,
};
Loading