Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
79bdb18
refactor: introduce pages plugin
tpluscode Jan 4, 2026
04f30e9
refactor: remove boilerplate from page HTML
tpluscode Jan 5, 2026
47a4707
feat: use relative paths
tpluscode Jan 9, 2026
bd40931
refactor: defer hydration and hydrate ourselves
tpluscode Jan 18, 2026
e803e9b
feat: simplest sort
tpluscode Jan 19, 2026
bab5cd9
junie: resource-label
tpluscode Jan 22, 2026
ec157e0
junie: template data more declarative
tpluscode Jan 23, 2026
a942a7a
refactor: declarative data bind of graphs
tpluscode Jan 23, 2026
b481707
feat: query page URLs
tpluscode Feb 3, 2026
93ab321
feat: open-styles for better CSS adoption
tpluscode Feb 4, 2026
752075a
refactor: plugin system with build support
tpluscode Feb 19, 2026
6a8fdaf
feat: build server pages modules with esbuild
tpluscode Feb 19, 2026
46d98f2
fix: production mode issues with esbuild splitting and module loading
tpluscode Feb 19, 2026
b1c4ad8
build(deps): extract dependencies and add ts-plugin-sparqlc
tpluscode Feb 24, 2026
d8d7b5b
Merge branch 'temp-branch' into pages
tpluscode Feb 27, 2026
5410dd0
build: complete the migration of pages plugin
tpluscode Feb 27, 2026
c9ff747
refactor: allow logging in vite-derived plugins
tpluscode Mar 2, 2026
a458d9f
feat(core): `appNs`
tpluscode Mar 2, 2026
890a812
chore: some logging
tpluscode Mar 2, 2026
5486bac
feat(pages): re-export `html`
tpluscode Mar 2, 2026
b500abc
fix: setting default value of `deferHydration`
tpluscode Mar 2, 2026
d525675
build(deps): update packages
tpluscode Mar 2, 2026
0f66f30
feat(pages): connectedCallback configuration to allow/disallow for se…
tpluscode Mar 3, 2026
4e4f587
refactor(pages): rename `PageRenderer` to `Page`
tpluscode Mar 3, 2026
351cbee
feat(pages): added `mainEntity` as page field
tpluscode Mar 3, 2026
73f07f6
chore: todo note
tpluscode Mar 3, 2026
e1d073a
refactor: use kopflos pages in example
tpluscode Mar 3, 2026
e090e39
build: ts and vite fixes
tpluscode Mar 4, 2026
f7f3a02
feat: conventions for loading page dependencies
tpluscode Mar 4, 2026
ba3471d
refactor: finish updating the example
tpluscode Mar 5, 2026
1dfee83
docs(pages): readme
tpluscode Mar 5, 2026
bca7b48
ci: added kopflos/pages to test matrix
tpluscode Mar 5, 2026
bb84cea
feat: make apiGraphs optional and allow plugins to add api graphs and…
tpluscode Mar 5, 2026
3d6380e
style: reformat
tpluscode Mar 5, 2026
79bc275
test: PageUrlTransform.test.ts
tpluscode Mar 5, 2026
ce4fee5
test: add tests for SparqlProcessor
tpluscode Mar 5, 2026
1d5e2d6
test: add test for patterns query
tpluscode Mar 5, 2026
d0644cf
ci: for mocha to work
tpluscode Mar 5, 2026
5e7a525
test: update config cases
tpluscode Mar 6, 2026
35042e4
test(express): remove obsolete test
tpluscode Mar 6, 2026
f15fa6f
ci: disable raw api-tuner output
tpluscode Mar 6, 2026
2128670
ci: save kopflos logs and api-tuner temp files
tpluscode Mar 6, 2026
6b6ae4c
ci: disable ulog color
tpluscode Mar 6, 2026
975d64c
ci: better debug api-tuner response data
tpluscode Mar 6, 2026
ab9d953
ci: combine artifact steps
tpluscode Mar 6, 2026
a694de7
ci: set TMPDIR
tpluscode Mar 6, 2026
86ce620
fix: actually bind `mainEntity`
tpluscode Mar 9, 2026
0d24fec
fix: load maps only on the client for now
tpluscode Mar 11, 2026
8acb952
Merge remote-tracking branch 'origin/master' into pages
tpluscode Mar 11, 2026
8045bec
test: executing page queries
tpluscode Mar 12, 2026
f54de97
test: pageParameters.test.ts
tpluscode Mar 12, 2026
d5a7e6c
test: our plugin and vite plugin
tpluscode Mar 12, 2026
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
5 changes: 5 additions & 0 deletions .changeset/fair-suns-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kopflos-cms/core": patch
---

Allow plugins to add watch paths using `watchPaths` method
5 changes: 5 additions & 0 deletions .changeset/lucky-zebras-find.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kopflos-cms/vite": patch
---

`log` field is now protected so that impementing plugins can log more easily
5 changes: 5 additions & 0 deletions .changeset/perky-birds-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kopflos-labs/pages": patch
---

Re-export `html` from lit for convenience
5 changes: 5 additions & 0 deletions .changeset/social-loops-say.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kopflos-labs/pages": patch
---

Added `(dis)allowConnectedCallback` arrays to `SsrOptions` to control which elements run `connectedCallback` in the browser.
5 changes: 5 additions & 0 deletions .changeset/spotty-emus-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kopflos-cms/core": patch
---

Added `appNs` `NamespaceBuilder` to the environment which creates named nodes relative to app base
5 changes: 5 additions & 0 deletions .changeset/two-colts-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kopflos-cms/core": patch
---

Making `apiGraphs` optional in config. By default, a graph `${baseIri}/api` will be used. Additionally, plugins can provide addtional API graphs using `apiGraph` method
18 changes: 16 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ jobs:
path: labs/html-template
- name: "@kopflos-labs/handlebars"
path: labs/handlebars
- name: "@kopflos-labs/pages"
path: labs/pages
- name: sparql-path-parser
path: packages/sparql-path-parser
steps:
Expand Down Expand Up @@ -82,7 +84,19 @@ jobs:
- run: npm ci
- run: docker compose up -d
working-directory: example
- run: npm run -w example start &
- run: npm run -w example start 2>&1 | tee example.log &
env:
log_color: off
- run: npx wait-on http://localhost:1429/plaque/newton-s-apple-tree-monash-university -t 30000

- run: npm run -w example test -- --debug --raw
- run: npm run -w example test -- --debug
env:
TMPDIR: ${{ runner.temp }}
- if: failure()
name: upload debug artifacts
uses: actions/upload-artifact@v4
with:
name: smoke-test-debug
path: |
example.log
${{ runner.temp }}/api-tuner*
14 changes: 9 additions & 5 deletions example/kopflos.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import ExpressMiddleware from '@kopflos-cms/express/middleware' // eslint-disabl
import Vite from '@kopflos-cms/vite'
import Hydra from '@kopflos-cms/hydra'
import Shacl from '@kopflos-cms/shacl'
import PluginPages from '@kopflos-labs/pages'

const baseIri = process.env.API_BASE || 'http://localhost:1429'
const dbUri = process.env.DB_URI || 'http://localhost:7878'

export default <KopflosConfig>{
baseIri,
apiGraphs: [baseIri + '/api'],
sparql: {
default: {
endpointUrl: dbUri + '/query?union-default-graph',
Expand All @@ -33,10 +33,6 @@ export default <KopflosConfig>{
],
}),
new Vite({
build: {
root: 'ui',
entrypoints: ['*.html'],
},
config: {
server: {
allowedHosts: ['read-the-plaque.lndo.site'],
Expand All @@ -47,5 +43,13 @@ export default <KopflosConfig>{
apis: [baseIri + '/api'],
}),
new Shacl(),
new PluginPages({
ssrOptions: {
disallowConnectedCallback: [
/^sl-/,
/^ol-/,
],
},
}),
],
}
7 changes: 0 additions & 7 deletions example/lib/templateData.ts

This file was deleted.

11 changes: 6 additions & 5 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,21 @@
"@kopflos-cms/shacl": "0.3.1",
"@kopflos-cms/vite": "0.3.4",
"@kopflos-labs/handlebars": "0.1.1",
"@kopflos-labs/html-template": "0.1.1",
"@kopflos-labs/lit": "0.1.1",
"@openlayers-elements/core": "^0.3.0",
"@openlayers-elements/maps": "^0.3.0",
"@kopflos-labs/pages": "0.0.0",
"@openlayers-elements/core": "^0.4.0",
"@openlayers-elements/maps": "^0.4.0",
"@shoelace-style/shoelace": "^2.17.1",
"@webcomponents/template-shadowroot": "^0.2.1",
"compression": "^1.7.4",
"cors": "^2.8.5",
"express": "^5.2.0",
"kopflos": "0.1.10",
"lit-element": "^4.1.1"
"lit": "^3.3.2",
"lit-rdf": "^0.1.0"
},
"devDependencies": {
"@types/express": "^5",
"api-tuner": "^0.5.3"
"api-tuner": "^0.5.4"
}
}
4 changes: 4 additions & 0 deletions example/pages/component/maps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import '@openlayers-elements/core/ol-map.js'
import '@openlayers-elements/maps/ol-layer-openstreetmap.js'
import '@openlayers-elements/maps/ol-marker-icon.js'
import '@openlayers-elements/core/ol-layer-vector.js'
18 changes: 18 additions & 0 deletions example/pages/component/my-header.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { LitElement, html, css } from 'lit'
import { customElement } from 'lit/decorators.js'
import { consumeFocusNode } from 'lit-rdf/mixins.js'

@customElement('my-header')
export class MyHeader extends consumeFocusNode(LitElement) {
public static get styles() {
return css`
h1 {
color: red
}
`
}

render() {
return html`<h1>${this.focusNode?.value}</h1>`
}
}
13 changes: 13 additions & 0 deletions example/pages/component/plaque-button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { consumeEnvironment, consumeFocusNode } from 'lit-rdf/mixins.js'
import { html, LitElement } from 'lit'
import { customElement } from 'lit/decorators.js'

@customElement('plaque-button')
export default class extends consumeEnvironment(consumeFocusNode(LitElement)) {
render() {
return html`<sl-button variant="primary" pill target="_blank"
href="https://readtheplaque.com/plaque/${this.focusNode?.out(this.rdf.ns.schema.identifier)}">See the
original
</sl-button>`
}
}
22 changes: 22 additions & 0 deletions example/pages/component/schema-geo-map-button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { consumeEnvironment, consumeFocusNode } from 'lit-rdf/mixins.js'
import { html, LitElement } from 'lit'
import { customElement } from 'lit/decorators.js'

@customElement('schema-geo-map-button')
export default class extends consumeEnvironment(consumeFocusNode(LitElement)) {
get latitude() {
return this.focusNode?.out(this.rdf.ns.schema.latitude).value
}

get longitude() {
return this.focusNode?.out(this.rdf.ns.schema.longitude).value
}

render() {
return html`
<sl-button variant="primary" pill target="_blank"
href="http://maps.google.com/maps?&z=21&t=m&q=loc:${this.latitude}+${this.longitude}">
See on Google Maps
</sl-button>`
}
}
30 changes: 30 additions & 0 deletions example/pages/component/schema-geo-map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { consumeEnvironment, consumeFocusNode } from 'lit-rdf/mixins.js'
import { html, isServer, LitElement } from 'lit'
import { customElement } from 'lit/decorators.js'

if (!isServer) {
import('./maps.js')
}

@customElement('schema-geo-map')
export default class extends consumeEnvironment(consumeFocusNode(LitElement)) {
get latitude() {
return this.focusNode?.out(this.rdf.ns.schema.latitude).value
}

get longitude() {
return this.focusNode?.out(this.rdf.ns.schema.longitude).value
}

render() {
return html`<ol-map slot="image" zoom="13" lat="${this.latitude}"
lon="${this.longitude}">
<ol-layer-openstreetmap></ol-layer-openstreetmap>
<ol-layer-vector z-index="1">
<ol-marker-icon src="https://openlayers-elements.netlify.app/icon.png"
lon="${this.longitude}"
lat="${this.latitude}"/>
</ol-layer-vector>
</ol-map>`
}
}
33 changes: 33 additions & 0 deletions example/pages/component/schema-image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { consumeEnvironment, consumeFocusNode } from 'lit-rdf/mixins.js'
import { css, html, LitElement, nothing } from 'lit'
import { customElement, property } from 'lit/decorators.js'

@customElement('schema-image')
export class SchemaImage extends consumeFocusNode(consumeEnvironment(LitElement)) {
static styles = css`
:host {
display: flex;
align-items: center;
height: 100%;
}

img {
max-width: 100%;
max-height: 100%;
}
`

@property({ type: String })
public alt?: string

protected render(): unknown {
const src = this.focusNode?.out(this.rdf.ns.schema.contentUrl).value
if (!src) {
return nothing
}

return html`
<img part="image" src="${src}" alt="${this.alt}"/>
`
}
}
File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions example/pages/plaque/[id].client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import 'lit-rdf/runtime/data-graph.js'
import '@shoelace-style/shoelace/dist/components/card/card.js'
import '@shoelace-style/shoelace/dist/components/button/button.js'
43 changes: 43 additions & 0 deletions example/pages/plaque/[id].html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="///cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.17.1/cdn/themes/light.css"/>

<style>
body[dsd-pending] {
display: none;
}

main {
display: flex;
justify-content: space-evenly;
}

sl-card {
width: 500px;
}

.card-overview small {
color: var(--sl-color-neutral-500);
}

.card-overview [slot='footer'] {
display: flex;
justify-content: space-between;
align-items: center;
}

ol-map {
height: 500px;
width: 100%;
}
</style>
</head>
<body dsd-pending>
<footer>
<p>&copy; 2024 Zazuko</p>
</footer>
</body>
</html>
57 changes: 57 additions & 0 deletions example/pages/plaque/[id].html.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { html, definePage } from '@kopflos-labs/pages'
import plaque from './plaque.rq'

export default definePage({
mainEntity: '/plaque/[id]',
queries: {
plaque,
},
head({ env, data }) {
const name = data.plaque
.has(env.ns.rdf.type, env.kopflos.appNs('/api/schema/Plaque'))
.out(env.ns.schema.name).value

return `<title> ${name} ::: Read the Plaque</title>`
},
body({ env }) {
return html`
<rdf-environment>
<data-graph data-graph="plaque">
<target-node target-class="${env.kopflos.appNs('/api/schema/Plaque').value}">
<header>
<traverse-graph property-path="schema:name">
<my-header></my-header>
</traverse-graph>
</header>
<main>
<sl-card class="card-overview">
<traverse-graph slot="image" property-path="schema:image">
<schema-image></schema-image>
</traverse-graph>

<resource-label property="schema:text"></resource-label>

<div slot="footer">
<plaque-button>
See the original
</plaque-button>
</div>
</sl-card>

<traverse-graph property-path="schema:geo">
<sl-card class="card-overview">
<schema-geo-map></schema-geo-map>

<div slot="footer">
<schema-geo-map-button>
See on Google Maps
</schema-geo-map-button>
</div>
</sl-card>
</traverse-graph>
</main>
</target-node>
</data-graph>
</rdf-environment>`
},
})
7 changes: 7 additions & 0 deletions example/pages/plaque/[id].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'lit-rdf'
import 'lit-rdf/components/rdf-environment.js'
import '../component/my-header.js'
import '../component/schema-image.js'
import '../component/plaque-button.js'
import '../component/schema-geo-map.js'
import '../component/schema-geo-map-button.js'
11 changes: 11 additions & 0 deletions example/pages/plaque/plaque.rq
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
PREFIX schema: <http://schema.org/>
PREFIX sparqlc: <https://sparqlc.described.at/>

CONSTRUCT {
?s ?p ?o
} {
BIND(sparqlc:param(schema:mainEntity) as ?plaque)
GRAPH ?plaque {
?s ?p ?o
}
}
File renamed without changes.
Loading
Loading