Node.js & PUG - Checking if card has array property in JSON file and printing key

So I’m creating an HTML template using node.js which takes in an array of card objects from a json file and uses the data contained within to generate a page to display the list of cards as links. When you click on a card, it displays information about the card. I’m having trouble with a few issues regarding how to print certain values of the card.

First, I’m having trouble with why the name and id of the card prints fine, but every other key prints as the code ‘card.key’ instead of the actual value.

Second, I have hundreds of cards (only listed 4 for this post though) and some of them are missing the rarity and mechanic keys. I’m trying to check if such keys exist before printing them out but I’m not quite sure how to alter my code to make it fit with pug’s language criteria and rules. If a card has a rarity property, I want to display a number of * characters to signify the rarity (e.g., 1 star for free, 2 for common, 3 for rare, 4 for epic, 5 for legendary). If the card has a mechanics array property, my template should include a “Mechanics:”
heading and list each of the mechanics strings contained in the array.

The page containing the info on a card seems to display fine when I don’t attempt to list the rarity or mechanic (aside from some values printing as card.key).

Here’s an example of what the page looks like when I click on the first card in the list:

Screenshot (1)

When I include the code for checking for rarity and mechanic properties, the card.pug page doesn’t seem to load anymore. I get the error “This site can’t be reached” and “localhost refused to connect.” I feel like I’m formatting my code wrong for this part. This is what it looks like with the rarity and mechanics code:

card.pug:

html
	head
		title #{card.name}
body

	div#main
		h1 #{card.name}
		br
		p Id: #{card.id}
		br
		p Class: #(card.cardClass)
		br
		p Set: #(card.set)
		br
		p Type: #(card.type)
		br
		p Artist: #(card.artist)
		br
		p Text: #(card.text)	

		if(card.hasOwnProperty('rarity:)){
			if(card.rarity = "FREE"){
				p Rarity: *
			}else if(card.rarity = "COMMON"){
				p Rarity: **
			}else if(card.rarity = "RARE"){
				p Rarity: ***
			)else if(card.rarity = "EPIC"){
				p Rarity: ****
			)else if(card.rarity = "LEGENDARY"){
				p Rarity: *****
			}
		}
		
		if(card.hasOwnProperty("mechanics")){
			p Mechanics: #(card.mechanics)
		}		

This is also a little side note, but I was wondering how I would go about listing the links for the first 3 cards in the json file instead of all of them? My cards.pug page looks like this

but as I mentioned, I have hundreds of cards, and would find it easier to only print the first 3 links instead of all of them. I know the code would look something like this:

const numCards = 3;
let cardData = require("./cards.json");
let cards = {}; 
for (let i = 0; i < numCards && i < cardData.length; i++) {
	cards[cardData[i].id] = cardData[i];
}

but I don’t know where this would go in my code.

Again, any help with these issues would be appreciated!

Here’s the rest of the code minus my cards.pug file as I’ve already included it:

server.js:

const pug = require("pug");
const fs = require("fs");
const http = require("http");
const url = require('url')

let cardData = require("./cards.json");
let cards = {}; 
cardData.forEach(card => {
	cards[card.id] = card;
});

//Initialize server
const server = http.createServer(function(request, response) {
	if (request.method === "GET") {
		if (request.url === "/cards") {		
			  response.statusCode = 200;
			  response.write(pug.renderFile("./views/cards.pug", { cards: cards }));
			  response.end();
		}else if (request.url.startsWith("/cards/")) {
			const paths = request.url.split("/");
			const cardId = paths[2];
			if (cards.hasOwnProperty(cardId)) {
				const targetCard = cards[cardId];
				response.statusCode = 200;
				response.write(
					pug.renderFile("./views/card.pug", { card: targetCard })
				);
				response.end();
				return;
			} else {
				response.statusCode = 404;
				response.end();
				return;
			}
		} else if (request.url.startsWith("/cards?")) {
			const params = request.url.split("?");
			const [_, value] = params[1].split("=");
			const limit = parseInt(value);
			if (limit < 1) {
				response.statusCode = 400;
				response.write("Invalid query");
				response.end();
				return;
			}
			const responseCards = Object.values(cards).slice(0, limit);
			response.statusCode = 200;
			response.write(
				pug.renderFile("./views/cards.pug", { cards: responseCards })
			);
			response.end();
			return;
		}
	} else {
		response.statusCode = 404;
		response.write("Unknown resource.");
		response.end();
	}
});

//Start server
server.listen(3000);
console.log("Server listening at http://localhost:3000");

cards.json:

[
	{
	"artist":"Arthur Bozonnet",
	"attack":3,
	"cardClass":"MAGE",
	"collectible":true,
	"cost":2,
	"dbfId":2545,
	"flavor":"And he can't get up.",
	"health":2,
	"id":"AT_003",
	"mechanics":["HEROPOWER_DAMAGE"],
	"name":"Fallen Hero",
	"rarity":"RARE",
	"set":"TGT",
	"text":"Your Hero Power deals 1 extra damage.",
	"type":"MINION"
	},

	{
	"artist":"Dan Scott",
	"attack":3,
	"cardClass":"MAGE",
	"collectible":true,
	"cost":4,
	"dbfId":2549,
	"flavor":"Is he aspiring or inspiring?  Make up your mind!",
	"health":5,
	"id":"AT_006",
	"mechanics":["INSPIRE"],
	"name":"Dalaran Aspirant",
	"rarity":"COMMON",
	"referencedTags":["SPELLPOWER"],
	"set":"TGT",
	"text":"<b>Inspire:</b> Gain <b>Spell Damage +1</b>.",
	"type":"MINION"
	},
	
	{
	"artist":"Andrew Hou",
	"attack":3,
	"cardClass":"MAGE",
	"collectible":true,
	"cost":3,
	"dbfId":2571,
	"flavor":"Does he sling spells, or do his spells linger about.  Who can say?",
	"health":4,
	"id":"AT_007",
	"mechanics":["BATTLECRY", "SCREECH"],
	"name":"Spellslinger",
	"rarity":"COMMON",
	"set":"TGT",
	"text":"<b>Battlecry:</b> Add a random spell to each player's hand.",
	"type":"MINION"
	},

	{
	"artist":"Christopher Moeller",
	"attack":6,
	"cardClass":"MAGE",
	"collectible":true,
	"cost":6,
	"dbfId":2544,
	"flavor":"The Grand Tournament has a \"No dragons allowed\" policy, but it's rarely enforced.",
	"health":6,
	"id":"AT_008",
	"name":"Coldarra Drake",
	"race":"DRAGON",
	"rarity":"EPIC",
	"set":"TGT",
	"text":"You can use your Hero Power any number of times.",
	"type":"MINION"
	}
]

cards.pug:

html
	head
		title Cards
body

	div#main
		h1 List of Cards:
		each card in cards
			a(href="/cards/" + card.id) #{card.name}
			br

At some point, you decided to forgo the {} (curly brackets) for () (parentheses)…

Does Pug use parentheses around the if conditions? Also, does it use curly brackets to denote scope?


I would write this line:

response.write(pug.renderFile("./views/cards.pug", { cards: cards }));

As:

response.write(pug.renderFile('./views/cards.pug', { cards: cards.slice(0,3) }));