Skip to content
Merged
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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# masonry-angular — workspace

[![npm](https://img.shields.io/npm/v/masonry-angular.svg)](https://www.npmjs.com/package/masonry-angular)
[![license](https://img.shields.io/npm/l/masonry-angular.svg)](LICENSE)

Angular workspace for the **masonry-angular** library and its example app.

**[npm](https://www.npmjs.com/package/masonry-angular)** ·
**[GitHub](https://github.com/MeAkib/masonry-angular)** ·
**[StackBlitz](https://stackblitz.com/github/MeAkib/masonry-angular/tree/main/examples/stackblitz)**

| Project | Path | |
| --- | --- | --- |
| `masonry-angular` | `projects/masonry-angular` | The publishable library. |
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"size:features": "npm run build:lib && node scripts/feature-size.mjs",
"verify:ssr": "npm run build:lib && node scripts/verify-ssr.mjs",
"verify:compat": "node scripts/verify-compat.mjs",
"verify:docs": "npm run build:lib && node scripts/verify-docs.mjs"
"verify:docs": "npm run build:lib && node scripts/verify-docs.mjs",
"postbuild": "node scripts/inject-meta.mjs"
},
"packageManager": "npm@11.12.1",
"engines": {
Expand Down
Binary file added projects/demo/public/og.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions projects/demo/src/app/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,31 @@ nav a.active {
main {
padding: 20px 10px;
}

.masthead .links {
display: flex;
flex-wrap: wrap;
gap: 14px;
align-items: center;
margin-top: 10px;
font-size: 0.85rem;
}

.masthead .links a {
color: var(--accent);
text-decoration: none;
border-bottom: 1px solid transparent;
}

.masthead .links a:hover {
border-bottom-color: currentcolor;
}

.masthead .links code {
padding: 2px 8px;
border: 1px solid var(--line);
border-radius: 6px;
background: var(--panel);
color: var(--muted);
font-size: 0.8rem;
}
19 changes: 19 additions & 0 deletions projects/demo/src/app/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@
<div>
<h1>masonry-angular</h1>
<p>Zero-dependency masonry for Angular — signal-based, zoneless and SSR-safe.</p>

<!-- Somebody who likes what they see here needs a way to reach the package
and the source without hunting for it. -->
<p class="links">
<a href="https://www.npmjs.com/package/masonry-angular" target="_blank" rel="noopener">
npm
</a>
<a href="https://github.com/MeAkib/masonry-angular" target="_blank" rel="noopener">
GitHub
</a>
<a
href="https://stackblitz.com/github/MeAkib/masonry-angular/tree/main/examples/stackblitz"
target="_blank"
rel="noopener"
>
StackBlitz
</a>
<code>npm i masonry-angular</code>
</p>
</div>

<nav>
Expand Down
39 changes: 38 additions & 1 deletion projects/demo/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,47 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Demo</title>
<title>masonry-angular — cascading grid layout for Angular</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />

<meta
name="description"
content="Zero-dependency masonry layout for Angular. For photo walls and for dashboards where cards have different heights. 8.6 KB, signal-based, zoneless, SSR-safe, Angular 17.1–22."
/>

<!--
__SITE_URL__ is replaced at build time by scripts/inject-meta.mjs, which
reads Vercel's VERCEL_PROJECT_PRODUCTION_URL. Open Graph requires an
absolute URL for og:image — a relative one is silently ignored, which is
exactly the failure where a shared link shows no preview at all.
-->
<meta property="og:type" content="website" />
<meta property="og:site_name" content="masonry-angular" />
<meta property="og:url" content="__SITE_URL__/" />
<meta property="og:title" content="masonry-angular — cascading grid layout for Angular" />
<meta
property="og:description"
content="Zero dependencies, 8.6 KB, Angular 17–22, SSR-safe. For photo walls and for dashboards that stop leaving gaps."
/>
<meta property="og:image" content="__SITE_URL__/og.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta
property="og:image:alt"
content="masonry-angular: a cascading grid of coloured cards at different heights."
/>

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="masonry-angular — cascading grid layout for Angular" />
<meta
name="twitter:description"
content="Zero dependencies, 8.6 KB, Angular 17–22, SSR-safe. For photo walls and for dashboards that stop leaving gaps."
/>
<meta name="twitter:image" content="__SITE_URL__/og.png" />

<link rel="canonical" href="__SITE_URL__/" />
</head>
<body>
<app-root></app-root>
Expand Down
51 changes: 51 additions & 0 deletions scripts/inject-meta.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Turns the `__SITE_URL__` placeholders in the built `index.html` into the real
* deployed origin.
*
* Open Graph needs an *absolute* URL for `og:image` — a relative one is ignored
* without complaint, and the result is a shared link that shows no preview at
* all. Since the URL is not known until the site is deployed, the source keeps
* a placeholder and this fills it in after the build.
*
* `VERCEL_PROJECT_PRODUCTION_URL` is the right variable: Vercel documents it as
* always set, even on preview deployments, specifically so that OG image URLs
* point at production. It carries no scheme, so `https://` is added here.
*
* npm runs this automatically after `npm run build`.
*/
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const INDEX = resolve(ROOT, 'dist/demo/browser/index.html');

/** Only used when building outside Vercel, so local builds still produce valid URLs. */
const FALLBACK = 'https://masonry-angular.vercel.app';

const domain = process.env['VERCEL_PROJECT_PRODUCTION_URL'];
const origin = domain ? `https://${domain}` : FALLBACK;

if (!existsSync(INDEX)) {
console.error(`inject-meta — no build output at ${INDEX}. Run "npm run build" first.`);
process.exit(1);
}

const before = readFileSync(INDEX, 'utf8');
const after = before.replaceAll('__SITE_URL__', origin);
const replaced = before.split('__SITE_URL__').length - 1;

if (replaced === 0) {
console.error(
'inject-meta — found no __SITE_URL__ placeholders in the built index.html.\n' +
' The social preview tags are probably missing or renamed; a shared link\n' +
' would show no preview card. Check projects/demo/src/index.html.',
);
process.exit(1);
}

writeFileSync(INDEX, after);
console.log(
`inject-meta — ${replaced} placeholder(s) -> ${origin}` +
(domain ? '' : ' (VERCEL_PROJECT_PRODUCTION_URL unset, used the fallback)'),
);
Loading