sourcehypertextpubliccrosswordscrosswords.js

const crosswords = [
	{
		title: "Archipelago",
		date: "2025 May 21",
		gridSource: `...ACAI.FOBS...
...DRYS.ICON...
...ZEALANDIA...
PUGET.ARC.LIMIT
ERASE.NAH.SLATE
NIL..IDLED..UBE
DEACONS.SOBERED
..PAST...DEMI..
ARAFURA.SOCOTRA
DIG..ATLAS..IIN
ATOLL.NUN.KAUAI
MASAI.IAD.NASAL
...KERGUELEN...
...EACH.ROAD...
...STAT.SADE...`,
		clueSource: {
			across: [
				"Brazilian smoothie berry",
				"Watch chains",
				"Teetotalers",
				"Picture of adoration",
				"Submerged continent encompassing Aotearoa, New Caledonia, and more",
				"Washington sound",
				"Curve",
				"Threshold",
				"Rub off",
				"“Yeah, ___, mate.”",
				"Cyber-magazine known for its contrarian “pitches”",
				"Nowt",
				"Stood by",
				"Purple yam popular in the Philippines",
				"Priest’s assistants",
				"Chilled out",
				"Gone by",
				"<i>The Substance</i> star Moore",
				"Sea between Australia and Indonesia",
				"Isolated Yemeni isle home to the dragon’s blood tree",
				"Hit the ground",
				"A man with the weight of the world on his shoulders",
				"“There’s no _ __ team” (1,2)",
				"Lagoon isle",
				"Ms. Monk?",
				"Hawaiian isle formerly home to the extinct ʻōʻō",
				"Kenyan nomads",
				"Year after <span class='all-sc'>I B.C.</span>",
				"Nosey?",
				"French Antarctic isle home to cabbage prized by sailors for its vitamin-<span class='all-sc'>C</span> content",
				"Every",
				"“The Rocky ____ to Dublin”",
				"“Right now!”",
				"“By Your Side” singer"
			],
			down: [
				"Woodworking tools",
				"Greek isle home to the ancient Minoan civilisation",
				"Palindromic Akkadian dawn-goddess",
				"What many words in this puzzle are",
				"Animals of Darwin’s fascination in 15-Down",
				"Repetitive condition, briefly",
				"Bubbles up",
				"Non-homeless slug",
				"Former central Asian sea",
				"Await action",
				"“I Write Sins Not Tragedies” singer Brendon",
				"Famous Ecuadorian isles home to tortoises, cormorants, and lava lizards",
				"Small Indian Ocean isle once home to 26-Down",
				"“So mote __ __” (2,2)",
				"Set up, as in golf",
				"Within, in Rome",
				"Foolish flightless birds",
				"De-___ Starbucks order",
				"American uni. that trademarked the word <span class='all-sc'>“THE”</span>",
				"Rebecca, to friends",
				"Moody nineties and noughties rock",
				"Freddie’s replacement in Queen",
				"“____ Hayworth and Shawshank Redemption” (later adapted into a snappier-titled film)",
				"Under the moon (2,5)",
				"Firebrand Vermont senator",
				"Music industry org.",
				"Indigo dye",
				"A feast on 50-Across",
				"The opposite of 4-Down, in a sense",
				"___ __ anchor (stay put) (3,2)",
				"Roll in the dough",
				"Emergency department (1,3,1)… or “on the” on the Amstel (3,2)",
				"Elvis’s record label",
				"Haitian spirit"
			]
		}
	}
];

// Make crosswords ready for play
for (const xw of crosswords) {
	xw.grid = xw.gridSource.split("\n").map(row =>
		row.split("").map(square => {
			if (square == ".") {
				return {
					isBlack: true,
					solution: null,
					guess: null,
					label: null
				};
			} else {
				return {
					isBlack: false,
					solution: square,
					guess: null,
					label: null
				};
			}
		})
	);

	let labelIdx = 1;
	xw.clues = [{}];

	for (let rowIdx = 0; rowIdx < xw.grid.length; rowIdx++) {
		for (let colIdx = 0; colIdx < xw.grid[rowIdx].length; colIdx++) {
			const square = xw.grid[rowIdx][colIdx];
			// If it’s on the first column or row, OR it’s just after a black square, give it a label
			if (
				!square.isBlack &&
				(colIdx == 0 ||
					rowIdx == 0 ||
					xw.grid[rowIdx - 1][colIdx].isBlack ||
					xw.grid[rowIdx][colIdx - 1].isBlack)
			) {
				square.label = labelIdx;

				// Add clues to that label number, depending on if it’s across or down
				xw.clues.push({});
				if (colIdx == 0 || xw.grid[rowIdx][colIdx - 1].isBlack) {
					xw.clues[labelIdx].across = xw.clueSource.across.shift();
				}
				if (rowIdx == 0 || xw.grid[rowIdx - 1][colIdx].isBlack) {
					xw.clues[labelIdx].down = xw.clueSource.down.shift();
				}

				labelIdx++;
			}
		}
	}
}

console.log(crosswords);