diff --git a/.gitignore b/.gitignore index b6d335aca..8c3f0b0e2 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ /http-tests/out /fuseki .claude/scheduled_tasks.lock +/cli/target diff --git a/CHANGELOG.md b/CHANGELOG.md index eb1c7ded1..3a125b3c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,28 @@ -## [Unreleased] +## [5.6.1] - 2026-07-26 ### Security -- SSRF: `URLValidator` now blocks wildcard/any-local (0.0.0.0, ::) addresses in addition to link-local and private ranges, and checks every address the host resolves to (narrowing the DNS-rebinding window). Loopback stays reachable for same-origin document/WebID dereferencing; the backend triplestore is site-local (already blocked). `ALLOW_INTERNAL_URLS` remains the development escape hatch (LNK-003/LNK-009) -- XXE: added `SecureXML` hardened parser factories — `XSLTMasterUpdater` parses with DTDs and external entities disabled, and the external responses parsed by `ldh:send-request` use secure processing (entity-expansion capped) with external entities disabled (LNK-005 residual) +- SSRF: `URLValidator` blocks wildcard/any-local (`0.0.0.0`, `::`) addresses and checks every resolved address; loopback stays reachable, `ALLOW_INTERNAL_URLS` remains the escape hatch (LNK-003/LNK-009) +- XXE: `SecureXML` hardened parser factories disable DTDs/external entities in `XSLTMasterUpdater` and `ldh:send-request` responses (LNK-005 residual) - Upgraded `java-jwt` 3.19.4 → 4.5.2 on the OAuth2/OIDC verification path -- Documented the pinned-truststore invariant behind the disabled hostname verification on internal HTTP clients +- Documented the pinned-truststore invariant behind disabled hostname verification on internal HTTP clients ### Added -- Unit tests for `AuthorizationFilter`: the HTTP-method → ACL access-mode contract (`GET`/`HEAD`→Read, `POST`→Append, `PUT`/`DELETE`/`PATCH`→Write), mode lookup, and the owner Read/Write/Append grant -- Loopback/wildcard `URLValidator` tests; JWKS-based `JWTVerifier` tests (valid, wrong issuer, wrong audience, expired, missing `kid`, bad signature) -- `AGENTS.md`: an agent-facing guide to driving a running instance's HTTP API — data model, WebID auth, read/write discipline (writes via `POST`/`PUT`/`PATCH` on document URLs; read-only SPARQL), content model, dataspaces, tooling -- Dependabot config (`.github/dependabot.yml`) for Maven, the Docker base image, and GitHub Actions updates; routine Maven minor/patch bumps grouped into one PR +- Unit tests for `AuthorizationFilter`'s HTTP-method → ACL access-mode contract, mode lookup, and owner grant +- Loopback/wildcard `URLValidator` tests; JWKS-based `JWTVerifier` tests +- `AGENTS.md`: agent-facing guide to driving a running instance's HTTP API +- Dependabot config (`.github/dependabot.yml`) for Maven, the Docker base image, and GitHub Actions ### Changed -- Cache TTLs configurable: the WebID model cache and the JWKS cache now read their expiration (seconds) from `WEBID_CACHE_EXPIRATION` / `JWKS_CACHE_EXPIRATION` (default 86400 = 1 day), via `CATALINA_OPTS` system properties like the `CLIENT_*` timeouts. Lowering `WEBID_CACHE_EXPIRATION` bounds how long a revoked WebID stays authenticated +- Cache TTLs configurable via `WEBID_CACHE_EXPIRATION` / `JWKS_CACHE_EXPIRATION` (default 86400s), bounding how long a revoked WebID stays authenticated +- CSR label rendering consolidated on Web-Client per-vocab templates; retired `$ldt:lang` for `$ac:langs` from `navigator.languages`; added client-side `ac:uuid()` (#323) +- Web-Client dependency bumped to 5.0.3 + +### Fixed +- View queries with a `FROM`/`FROM NAMED` clause returned `400`; `ldh:wrap-describe` now hoists the clause to the outer `DESCRIBE` +- Duplicate bilingual widget headings when the browser language matched neither value (#323) +- Language badge leaking into view headings (e.g. `enCurrent members`) +- `acl:mode()` went stale on fetch-less tab-pane switches; flags now re-synced from the activated pane +- Modal live-search debounce logged an unsupported-scheme fetch from `document="ixsl:page()"` +- Left-sidebar flyout clipped on short viewports; now scrolls ## [5.6.0] - 2026-07-08 ### Added diff --git a/README.md b/README.md index b1f153c76..8198c5915 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ We are building LinkedDataHub primarily for: What makes LinkedDataHub unique is its completely _data-driven architecture_: applications and documents are defined as data, managed using a single generic HTTP API and presented using declarative technologies. The default application structure and user interface are provided, but they can be completely overridden and customized. Unless a custom server-side processing is required, no imperative code such as Java or JavaScript needs to be involved at all. +XHTML documents can be edited in-place using a built-in RDFa-aware rich text editor — annotations link selected text directly to Knowledge Graph terms, embedding machine-readable RDF statements in the markup without leaving the page. + **Follow the [Get started](https://atomgraph.github.io/LinkedDataHub/linkeddatahub/docs/get-started/) guide to LinkedDataHub.** The setup and basic configuration sections are provided below and should get you running. **LinkedDataHub is also available as a free AWS Marketplace product!** AWS Marketplace diff --git a/pom.xml b/pom.xml index 50635e15f..50c92c80f 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.atomgraph linkeddatahub - 5.6.1 + 5.6.2-SNAPSHOT ${packaging.type} AtomGraph LinkedDataHub @@ -46,7 +46,7 @@ https://github.com/AtomGraph/LinkedDataHub scm:git:git://github.com/AtomGraph/LinkedDataHub.git scm:git:git@github.com:AtomGraph/LinkedDataHub.git - linkeddatahub-5.6.1 + linkeddatahub-5.5.4 @@ -339,7 +339,7 @@ inline-xml-entities - package + pre-integration-test iterator @@ -377,14 +377,14 @@ install-node-and-npm - package + pre-integration-test generate-sef npx - package + pre-integration-test xslt3-he -t -xsl:${project.build.directory}/${build.warName}${saxon-js.stylesheet} -export:${project.build.directory}/${build.warName}${saxon-js.stylesheet}.sef.json -nogo -ns:##html5 -relocate:on diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css index 0e19e5ebd..a2a07d9e1 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css @@ -44,6 +44,7 @@ ul.dropdown-menu ul { margin: 0; } .action-bar #doc-controls { text-align: right; padding-top: 5px; } .action-bar #doc-controls .btn-edit { margin-top: -5px; margin-left: 10px; } .action-bar p.alert { margin-bottom: 0; } +body:has(#edit-toolbar) .action-bar { border-bottom: 1px solid #aaa; } .nav-header.btn { color: inherit; } .btn.btn-primary.create-action { background-image: url('../icons/ic_note_add_white_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding-left: 40px; /* height: 30px; */ } .btn.create-action, a.create-action { background-image: url('../icons/ic_note_add_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding-left: 40px; /* height: 30px; */ } @@ -152,6 +153,8 @@ h2.item-logo { background-image: url('../icons/file.svg'); background-position: .modal-footer { position: sticky; bottom: 0; background-color: white; z-index: 1060; } .modal-first-time-message { margin-left: 0; width: 80%; left: 10%; } .modal-first-time-message .hero-unit { margin-bottom: 0; } +/* Annotation overlay */ +#rdfa-editor-overlay { position: absolute; min-width: 360px; max-width: 520px; z-index: 10001; } .control-group.endpoint-classes ul { max-height: 20em; overflow: auto; } .nav-tabs > li > a, .pager > li > a.active { cursor: pointer; } .pager > li.previous > a { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/ic_navigate_before_black_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; height: 24px; } @@ -180,8 +183,11 @@ button.add-typeahead { width: 219px; } .description { display: none; } .content .dl-horizontal { max-height: 35em; overflow: auto; } div[typeof="https://w3id.org/atomgraph/linkeddatahub#XHTML"] .main { font-size: larger; line-height: 25px; } +div[typeof="https://w3id.org/atomgraph/linkeddatahub#XHTML"]:not(:has(form)) .main { cursor: pointer; } +div[typeof="https://w3id.org/atomgraph/linkeddatahub#XHTML"] .btn-edit { display: none; } div[typeof="https://w3id.org/atomgraph/linkeddatahub#XHTML"] .form-horizontal .control-label { display: none; } div[typeof="https://w3id.org/atomgraph/linkeddatahub#XHTML"] .form-horizontal .controls { margin-left: 0; } +div[typeof="https://w3id.org/atomgraph/linkeddatahub#XHTML"] form fieldset { border: none; } .span12.progress .row-block-controls { background-color: #e9ecef; } .span12.progress .bar { height: 20px; } /* .content .btn.add-typeahead { margin-top: -10px; } */ @@ -210,4 +216,18 @@ object { display: block; margin: auto; max-height: 400px; overflow: hidden; widt .ol-overlay-container { width: 60%; max-height: 75%; background-color: white; overflow: auto; } .ol-overlay-container img { max-width: 100%; } /* SVG graph specific */ -circle { cursor: move; } \ No newline at end of file +circle { cursor: move; } +/* RDFa editor specific */ +.editor-bar { position: sticky; top: calc(var(--action-bar-top, 51px) + 50px); z-index: 998; background: #dfdfdf; padding: 0; box-shadow: none; display: flex; align-items: center; } +#edit-toolbar { order: -1; margin-right: auto; display: flex; gap: 6px; align-items: center; } +#edit-toolbar button, #edit-toolbar select { padding: 4px 8px; border: 1px solid #ccc; border-radius: 4px; background: white; font-size: 13px; font-family: inherit; cursor: pointer; margin-top: auto; margin-bottom: auto; } +#edit-toolbar button:disabled { opacity: 0.4; cursor: default; } +#edit-toolbar button:hover { background: #f5f5f5; } +#edit-toolbar button[aria-pressed="true"] { background: #e3f0ff; border-color: #6aa3e0; color: #1a5fb4; } +#edit-toolbar .tb-group { display: flex; gap: 6px; align-items: center; } +#edit-toolbar .tb-group + .tb-group { border-left: 1px solid #e0e0e0; padding-left: 6px; } +#edit-toolbar .tb-group.table-ops.active { background: #e3f0ff; border-radius: 4px; } +.edit-dialog { background: white; border: 1px solid #ccc; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,.2); padding: 12px; min-width: 280px; z-index: 10000; } +.edit-dialog .rdfa-editor-ui .action-buttons { margin-top: 10px; } +.edit-dialog .rdfa-editor-ui .checkbox-label { display: inline-flex; gap: 6px; align-items: center; font-weight: 400; margin-top: 8px; } +.editor-bar:not(:has(#edit-toolbar)), body:not(:has(.rdfa-editor-content)) .editor-bar, body:not(:has(.rdfa-editor-content)) #rdfa-editor-breadcrumb { display: none; } diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/rdfa-editor.css b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/rdfa-editor.css new file mode 100644 index 000000000..bbae2296f --- /dev/null +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/rdfa-editor.css @@ -0,0 +1,601 @@ +/* + * rdfa-editor.css - the RDFa editor's UI contract: annotation overlay, edit + * dialogs, toolbar, block chrome and drag-and-drop marks, ToC drawer, + * breadcrumb bar, lint markers, RDFa highlighting and the output modal. + * + * Host page requirements: include this stylesheet and give the editable + * container (.rdfa-editor-content) enough left padding (>= 2.5em) for the block drag + * handles, which render in the gutter outside each block's box. + */ + +/* RDFa Visual Styling - Subtle dashed borders */ + .rdfa-editor-content *[property] { + border: 1px dashed #4caf50; + padding: 1px 2px; + cursor: pointer; + transition: background-color 0.2s, border-color 0.2s; + } + +.rdfa-editor-content *[property]:hover { + background-color: rgba(76, 175, 80, 0.1); + border-color: #2e7d32; + } + +.rdfa-editor-content *[typeof] { + border: 1px dashed #9c27b0; + padding: 1px 2px; + cursor: pointer; + transition: background-color 0.2s, border-color 0.2s; + } + +.rdfa-editor-content *[typeof]:hover { + background-color: rgba(156, 39, 176, 0.1); + border-color: #7b1fa2; + } + +.rdfa-editor-content *[about] { + border: 1px dashed #2196f3; + padding: 1px 2px; + cursor: pointer; + transition: background-color 0.2s, border-color 0.2s; + } + +.rdfa-editor-content *[about]:hover { + background-color: rgba(33, 150, 243, 0.1); + border-color: #1976d2; + } + +.rdfa-editor-content *[resource] { + border: 1px dashed #ff9800; + padding: 1px 2px; + cursor: pointer; + transition: background-color 0.2s, border-color 0.2s; + } + +.rdfa-editor-content *[resource]:hover { + background-color: rgba(255, 152, 0, 0.1); + border-color: #f57c00; + } + +/* Invalid selection flash animation */ + @keyframes selection-flash { + 0% { background-color: transparent; } + 25% { background-color: rgba(244, 67, 54, 0.4); } + 50% { background-color: rgba(244, 67, 54, 0.6); } + 75% { background-color: rgba(244, 67, 54, 0.4); } + 100% { background-color: transparent; } + } + +.invalid-selection-flash { + animation: selection-flash 0.6s ease-in-out 2; + } + +.rdfa-editor-content > * { + position: relative; + } + +/* nested draggable blocks position their own handle (chrome is their first + child); handles stack per nesting level, each at its block's own indent */ + .rdfa-editor-content *:has(> [data-role="chrome"]) { + position: relative; + } + +/* invisible gutter strip: keeps the block hovered while the pointer + travels to the drag handle, which sits outside the block box */ + .rdfa-editor-content > *::before { + content: ''; + position: absolute; + left: -2.25em; + top: 0; + bottom: 0; + width: 2.25em; + } + +/* nested blocks get a narrower gutter, inside the parent's indentation */ + .rdfa-editor-content > * *:has(> [data-role="chrome"])::before { + content: ''; + position: absolute; + left: -1.5em; + top: 0; + bottom: 0; + width: 1.5em; + } + +/* a blockquote has no intrinsic child indentation, so its handle and its first + block's handle would coincide; the editing view indents quote content to give + each nesting level its own gutter column (lists and cells indent natively). + The quote bar (Markdown/Bootstrap convention) makes the container visible - + a normalized blockquote > p would otherwise read as a plain paragraph */ + .rdfa-editor-content blockquote { + padding-left: 2em; + border-left: 4px solid #e0e0e0; + color: #616161; + } + +/* the editing-DOM run wrapper (mixed flow content, e.g.
  • text
      ...) renders + like the bare inline run it stands for; unwrapped again at canonicalization */ + .rdfa-editor-content p.rdfa-editor-run { + margin: 0; + } + +.rdfa-editor-content figure { + margin: 16px 0; + } + +.rdfa-editor-content figure img { + display: block; + max-width: 400px; + } + +/* Table blocks: cell borders make empty cells clickable while editing. + Class-free, so canonical output (stored content) keeps host-page styling */ + .rdfa-editor-content table { + border-collapse: collapse; + margin: 16px 0; + } + +.rdfa-editor-content th, + .rdfa-editor-content td { + border: 1px solid #e0e0e0; + padding: 4px 8px; + min-width: 2em; + vertical-align: top; + } + +.rdfa-editor-content th { + background: #fafafa; + } + +.rdfa-editor-content caption { + caption-side: top; + text-align: left; + padding: 4px 0; + color: #757575; + } + +.rdfa-editor-content [contenteditable="true"]:focus { + outline: 2px solid rgba(33, 150, 243, 0.35); + outline-offset: 2px; + } + +/* A block image can't hold a caret; when focused it is the selected navigation + target, so it gets a stronger outline than the (caret-bearing) editable hosts */ + .rdfa-editor-content img:focus { + outline: 2px solid rgba(33, 150, 243, 0.7); + outline-offset: 2px; + } + +/* Object blocks (RDF-defined islands): the placeholder div renders as a card; + its RDFa definition spans are invisible - only the injected rendering shows. + Focused = selected navigation target, mirroring the image island */ + .rdfa-editor-content .rdfa-editor-island { + border: 1px solid #e0e0e0; + border-radius: 4px; + background: #fafafa; + padding: 8px 12px; + margin: 16px 0; + } + +.rdfa-editor-content .rdfa-editor-island > span[property] { + display: none; + } + +.rdfa-editor-content .rdfa-editor-island:focus { + outline: 2px solid rgba(33, 150, 243, 0.7); + outline-offset: 2px; + } + +.rdfa-editor-content .rdfa-editor-island.rdfa-editor-loading { + opacity: 0.5; + } + +.rdfa-editor-content .rdfa-editor-island [data-role="rendering"] table { + margin: 8px 0; + } + +/* Block chrome (drag handle) - ephemeral, data-role stripped on serialization */ + [data-role="chrome"] { + visibility: hidden; + position: absolute; + top: 2px; + left: -1.5em; + color: #9e9e9e; + font-size: 14px; + cursor: grab; + user-select: none; + border: none; + } + +.rdfa-editor-content *:hover > [data-role="chrome"] { + visibility: visible; + } + +/* Drag-and-drop feedback (v6 conventions) - any nesting depth */ + .rdfa-editor-content .dragging { + opacity: 0.4; + } + +.rdfa-editor-content .drop-before { + box-shadow: 0 -3px 0 0 #2196f3; + } + +.rdfa-editor-content .drop-after { + box-shadow: 0 3px 0 0 #2196f3; + } + +/* dropping INTO a cell highlights the cell itself, not an edge */ + .rdfa-editor-content .drop-into { + box-shadow: inset 0 0 0 2px #2196f3; + } + + +/* Slash menu (/ to insert a block) */ + #slash-menu { + background: white; + border: 1px solid #e0e0e0; + border-radius: 8px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); + padding: 6px; + min-width: 220px; + max-height: 320px; + overflow-y: auto; + z-index: 10000; + } + +.rdfa-editor-ui .slash-filter { + width: 100%; + padding: 7px 9px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 14px; + box-sizing: border-box; + margin-bottom: 6px; + } + +.rdfa-editor-ui .slash-items { + list-style: none; + margin: 0; + padding: 0; + } + +.rdfa-editor-ui .slash-item { + padding: 7px 10px; + border-radius: 4px; + font-size: 14px; + color: #212121; + cursor: pointer; + } + +.rdfa-editor-ui .slash-item:hover, + .rdfa-editor-ui .slash-item[aria-selected="true"] { + background: #e3f2fd; + color: #0d47a1; + } + +/* ToC jumps land below the fixed navbar */ + .rdfa-editor-content > * { + scroll-margin-top: 76px; + scroll-margin-bottom: 48px; + } + +/* ToC drawer (Fonto-style outline view) */ + #toc-drawer { + position: fixed; + top: 64px; + left: 0; + bottom: 44px; + width: 260px; + overflow-y: auto; + background: white; + border-right: 1px solid #e0e0e0; + box-shadow: 2px 0 4px rgba(0, 0, 0, 0.05); + padding: 12px 16px; + z-index: 900; + } + +#toc-drawer h2 { + font-size: 14px; + color: #555; + margin: 0 0 8px 0; + padding-right: 20px; + } + +#toc-drawer .toc-close { + position: absolute; + right: 8px; + top: 6px; + background: none; + border: none; + padding: 0 4px; + font-size: 22px; + line-height: 1; + color: #999; + cursor: pointer; + } + +#toc-drawer .toc-close:hover { + color: #333; + } + +#toc-drawer ul { + list-style: none; + padding-left: 0; + margin: 4px 0; + } + +#toc-drawer ul ul { + padding-left: 14px; + } + +.rdfa-editor-ui .toc-item { + padding: 2px 0; + } + +.rdfa-editor-ui .toc-label { + cursor: pointer; + display: block; + padding: 2px 6px; + border-radius: 4px; + font-size: 13px; + } + +.rdfa-editor-ui .toc-label:hover { + background: #e3f2fd; + } + +#toc-drawer .drop-before { + box-shadow: 0 -3px 0 0 #2196f3; + } + +#toc-drawer .drop-after { + box-shadow: 0 3px 0 0 #2196f3; + } + +#toc-drawer .dragging { + opacity: 0.4; + } + +/* Subject inspector drawer (read-only RDFa property sheet) */ + #inspector-drawer { + position: fixed; + top: 64px; + right: 0; + bottom: 44px; + width: 300px; + overflow-y: auto; + background: white; + border-left: 1px solid #e0e0e0; + box-shadow: -2px 0 4px rgba(0, 0, 0, 0.05); + padding: 12px 16px; + z-index: 900; + } + +#inspector-drawer h2 { + font-size: 14px; + color: #555; + margin: 0 0 8px 0; + padding-right: 20px; + } + +#inspector-drawer .inspector-close { + position: absolute; + right: 8px; + top: 6px; + background: none; + border: none; + padding: 0 4px; + font-size: 22px; + line-height: 1; + color: #999; + cursor: pointer; + } + +#inspector-drawer .inspector-close:hover { + color: #333; + } + +#inspector-subject { + margin-bottom: 12px; + padding-bottom: 8px; + border-bottom: 1px solid #e0e0e0; + } + +.rdfa-editor-ui .inspector-subject-iri { + display: block; + font-family: 'Courier New', monospace; + font-size: 13px; + color: #1565c0; + word-break: break-all; + margin-bottom: 6px; + } + +.rdfa-editor-ui .inspector-type { + display: inline-block; + background: #f3e5f5; + color: #7b1fa2; + border-radius: 10px; + padding: 1px 8px; + font-size: 11px; + margin-right: 4px; + } + +.rdfa-editor-ui .inspector-row { + padding: 5px 0; + border-bottom: 1px solid #f0f0f0; + font-size: 13px; + } + +.rdfa-editor-ui .inspector-pred { + display: block; + font-family: 'Courier New', monospace; + color: #2e7d32; + } + +.rdfa-editor-ui .inspector-obj { + display: block; + color: #333; + margin-top: 2px; + word-break: break-word; + } + +.rdfa-editor-ui .inspector-obj-iri { + font-family: 'Courier New', monospace; + color: #1976d2; + } + +.rdfa-editor-ui .inspector-obj-dt, + .rdfa-editor-ui .inspector-obj-lang { + color: #9e9e9e; + font-size: 11px; + margin-left: 6px; + } + +/* Breadcrumb bar (Fonto-style element path + RDFa subject) */ + #rdfa-editor-breadcrumb { + position: fixed; + left: 0; + right: 0; + bottom: 0; + background: white; + border-top: 1px solid #e0e0e0; + padding: 8px 20px; + display: flex; + justify-content: space-between; + align-items: center; + font-size: 13px; + z-index: 1000; + } + +.rdfa-editor-ui .crumb { + cursor: pointer; + color: #1976d2; + } + +.rdfa-editor-ui .crumb:hover { + text-decoration: underline; + } + +.rdfa-editor-ui .crumb-sep { + color: #9e9e9e; + margin: 0 4px; + } + +#rdfa-editor-breadcrumb-subject { + font-family: 'Courier New', monospace; + font-size: 12px; + color: #1565c0; + } + +.lint-badge { + border: none; + font-family: "Roboto", sans-serif; + background: #f44336; + color: white; + border-radius: 10px; + padding: 2px 10px; + font-size: 12px; + cursor: pointer; + margin-left: 12px; + } + +/* RDFa validation markers (class only - stripped by canonicalization) */ + .rdfa-editor-content .rdfa-invalid { + text-decoration: underline wavy #f44336; + text-decoration-skip-ink: none; + } + +/* Modal Dialog */ +#output-modal { + position: fixed; + z-index: 10001; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + } + +.rdfa-editor-ui .modal-content { + background-color: white; + padding: 30px; + border-radius: 8px; + width: 90%; + max-width: 900px; + max-height: 80vh; + overflow-y: auto; + position: relative; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); + } + +.rdfa-editor-ui .modal-close { + position: absolute; + right: 20px; + top: 15px; + font-size: 32px; + font-weight: bold; + color: #999; + cursor: pointer; + line-height: 1; + transition: color 0.2s; + } + +.rdfa-editor-ui .modal-close:hover { + color: #333; + } + +.rdfa-editor-ui #output-download { + position: absolute; + right: 60px; + top: 22px; + padding: 5px 14px; + border: 1px solid #2196f3; + border-radius: 4px; + background: white; + color: #2196f3; + font-size: 13px; + font-weight: 500; + font-family: inherit; + cursor: pointer; + transition: background-color 0.2s, color 0.2s; + } + +.rdfa-editor-ui #output-download:hover { + background: #2196f3; + color: white; + } + +.rdfa-editor-ui .modal-content h3 { + margin-top: 0; + color: #333; + padding-right: 40px; + } + +.rdfa-editor-ui .modal-content pre { + margin: 15px 0 0 0; + padding: 15px; + background-color: #f5f5f5; + border: 1px solid #e0e0e0; + border-radius: 4px; + font-family: 'Courier New', monospace; + font-size: 12px; + white-space: pre-wrap; + word-wrap: break-word; + overflow-x: auto; + } + +/* links are editable text: a plain click places the caret (I-beam, not a pointer that + would falsely promise navigation); Ctrl/Cmd+Click opens the href */ +.rdfa-editor-content a[href] { + cursor: text; +} + +/* the annotated selection stays visible while the overlay form has focus */ +.rdfa-editor-selection-hint { + position: absolute; + background: rgba(11, 87, 208, 0.22); + pointer-events: none; + z-index: 999; +} diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/admin/signup.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/admin/signup.xsl index 00e493f4d..e0d56de28 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/admin/signup.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/admin/signup.xsl @@ -172,7 +172,7 @@ exclude-result-prefixes="#all"> - + @@ -327,7 +327,7 @@ exclude-result-prefixes="#all"> - + diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block.xsl index 96fa08abf..1f0383fa2 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block.xsl @@ -203,6 +203,20 @@ exclude-result-prefixes="#all" + + + + + + + + + + + + + @@ -309,8 +323,47 @@ exclude-result-prefixes="#all" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -325,8 +378,14 @@ exclude-result-prefixes="#all" - + + + + + + + @@ -362,7 +421,7 @@ exclude-result-prefixes="#all" - + diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/chart.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/chart.xsl index 726a0b9fa..0f2976dd4 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/chart.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/chart.xsl @@ -272,11 +272,11 @@ exclude-result-prefixes="#all"
      diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/query.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/query.xsl index 13682e71a..a1944e0e3 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/query.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/query.xsl @@ -225,22 +225,22 @@ exclude-result-prefixes="#all"
      diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl index 269fd4b34..c309ecd42 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl @@ -219,7 +219,7 @@ exclude-result-prefixes="#all" - + @@ -817,7 +817,7 @@ exclude-result-prefixes="#all" @@ -841,14 +841,14 @@ exclude-result-prefixes="#all" @@ -901,7 +901,7 @@ exclude-result-prefixes="#all" - + @@ -1190,7 +1190,7 @@ exclude-result-prefixes="#all"