Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Markdown review format #188

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
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
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ npm install letterboxd --save

## usage

### function(username, [callback])
### function(username, [format], [callback])

Returns a promise if no callback is provided.

Expand All @@ -26,6 +26,18 @@ letterboxd("rubencordeiro")
.catch((error) => console.log(error));
```

#### format

Pass “markdown” as the optional `format` parameter for Markdown output in each film’s review.

```javascript
import letterboxd from "letterboxd";

letterboxd("rubencordeiro", "markdown")
.then((items) => console.log(items))
.catch((error) => console.log(error));
```

#### output

output is an array of items.
Expand All @@ -50,7 +62,7 @@ items of note for the list type:
image: { tiny: "...", small: "...", medium: "...", large: "..." },
},
rating: { text: "★★★★", score: 4 },
review: "proper cute, funny and interesting through out. ...",
review: "proper cute, funny and interesting through out. Co-directed by Byron Howard, who also directed Tangled.",
spoilers: false,
isRewatch: false,
date: { watched: 1463702400000, published: 1463784779000 },
Expand Down Expand Up @@ -84,3 +96,25 @@ items of note for the list type:
//...
];
```

If “markdown” is passed as the format parameter then HTML elements in the review text will be converted to Markdown:

```javascript
[
{
type: "diary",
film: {
title: "Zootopia",
year: "2016",
image: { tiny: "...", small: "...", medium: "...", large: "..." },
},
rating: { text: "★★★★", score: 4 },
review: "_proper_ cute, funny and interesting through out. Co-directed by Byron Howard, who also directed [Tangled](https://letterboxd.com/film/tangled-2010/).",
spoilers: false,
isRewatch: false,
date: { watched: 1463702400000, published: 1463784779000 },
uri: "https://letterboxd.com/zoetrope69/film/zootopia/",
},
//...
```

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"license": "ISC",
"dependencies": {
"cheerio": "^1.0.0-rc.10",
"node-fetch": "^2.6.6"
"node-fetch": "^2.6.6",
"turndown": "^7.1.2"
},
"devDependencies": {
"cross-env": "7.0.3",
Expand Down
40 changes: 34 additions & 6 deletions src/letterboxd.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fetch from "node-fetch";
import cheerio from "cheerio";
import TurndownService from 'turndown';

function isListItem(element) {
// if the list path is in the url
Expand Down Expand Up @@ -132,6 +133,33 @@ function getReview(element) {
return review;
}

function getReviewAsMarkdown(element) {
const description = element.find("description").text();

const $ = cheerio.load(description);

const reviewParagraphs = $("p").slice(1);

let review = "";

// if there is no review return the item
if (reviewParagraphs.length <= 0) {
return review;
}

// the rest of description is a review, if there is no review the string 'Watched on ' will appear
// this assumes you didn't write the 'Watched on ' string in your review... weak
if (reviewParagraphs.last().text().includes("Watched on ")) {
return review;
}

review = reviewParagraphs.toString();
const turndownService = new TurndownService();
const reviewMarkdown = turndownService.turndown(review);

return reviewMarkdown;
}

function getListFilms(element) {
const description = element.find("description").text();
const $ = cheerio.load(description);
Expand Down Expand Up @@ -220,7 +248,7 @@ function isListRanked(element) {
return isOrderedListPresent;
}

function processItem(element) {
function processItem(element, reviewFormat) {
// there are two types of items: lists and diary entries

if (isListItem(element)) {
Expand Down Expand Up @@ -252,7 +280,7 @@ function processItem(element) {
image: getImage(element),
},
rating: getRating(element),
review: getReview(element),
review: reviewFormat == 'markdown' ? getReviewAsMarkdown(element): getReview(element),
spoilers: getSpoilers(element),
isRewatch: getIsRewatch(element),
uri: getUri(element),
Expand All @@ -263,7 +291,7 @@ function invalidUsername(username) {
return !username || username.trim().length <= 0;
}

function getDiaryData(username) {
function getDiaryData(username, reviewFormat) {
const uri = `https://letterboxd.com/${username}/rss/`;

return fetch(uri)
Expand All @@ -285,20 +313,20 @@ function getDiaryData(username) {
const items = [];

$("item").each((i, element) => {
items[i] = processItem($(element));
items[i] = processItem($(element), reviewFormat);
});

return items;
});
}

function letterboxd(username) {
function letterboxd(username, reviewFormat) {
// check if a valid username has been passed in
if (invalidUsername(username)) {
return Promise.reject(new Error("No username sent as a parameter"));
}

return getDiaryData(username);
return getDiaryData(username, reviewFormat);
}

export default letterboxd;