Guides image + draft gating, audit retention, ADR-015 gate, backup credential redaction
This commit is contained in:
@@ -72,8 +72,27 @@
|
||||
<pre :ref="el => registerCode(block.id, el)"><code>{{ block.text }}</code></pre>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
The image is fetched by script, not by the browser.
|
||||
|
||||
An <img src> is a plain browser request: it carries no Authorization
|
||||
header, and this app keeps its JWT in one. So a direct src against the
|
||||
authenticated image route is a 401 and a broken-image icon for every
|
||||
reader - which is exactly how this shipped. Fetching through the api
|
||||
client sends the token, and it resolves against the client's baseURL, so
|
||||
it also survives a subpath mount that a stored '/api/...' string does
|
||||
not.
|
||||
|
||||
A failure says so in words. A guide whose screenshot is missing must not
|
||||
look like a guide that never had one.
|
||||
-->
|
||||
<figure v-else-if="block.type === 'image'" class="gb-figure">
|
||||
<img :src="block.url" :alt="block.alt || ''" loading="lazy">
|
||||
<img v-if="imageState(block).src" :src="imageState(block).src"
|
||||
:alt="block.alt || ''">
|
||||
<p v-else-if="imageState(block).failed" class="gb-imagefailed">
|
||||
Image unavailable{{ block.alt ? ': ' + block.alt : '' }}
|
||||
</p>
|
||||
<p v-else class="gb-imageloading">Loading image...</p>
|
||||
<figcaption v-if="block.caption">{{ block.caption }}</figcaption>
|
||||
</figure>
|
||||
|
||||
@@ -97,8 +116,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, toRef } from 'vue'
|
||||
import { renderInline } from '../utils/inline.js'
|
||||
import { useGuideImages } from '../utils/images.js'
|
||||
|
||||
const props = defineProps({
|
||||
blocks: { type: Array, default: () => [] },
|
||||
@@ -112,6 +132,9 @@ const selected = ref('')
|
||||
const codeNodes = {}
|
||||
function registerCode (id, el) { if (el) codeNodes[id] = el }
|
||||
|
||||
// Images are fetched by script, not by <img src>; see utils/images.js.
|
||||
const { state: imageState } = useGuideImages(toRef(props, 'blocks'))
|
||||
|
||||
function inline (text) {
|
||||
return renderInline(text)
|
||||
}
|
||||
@@ -226,6 +249,12 @@ function select (block) {
|
||||
|
||||
.gb-figure { margin: 0 0 1.2rem; }
|
||||
.gb-figure img { max-width: 100%; height: auto; border: 1px solid var(--border); border-radius: 4px; }
|
||||
.gb-imageloading, .gb-imagefailed {
|
||||
margin: 0; padding: 0.75rem 1rem; border: 1px dashed var(--border);
|
||||
border-radius: 4px; font-size: 0.9rem;
|
||||
}
|
||||
.gb-imageloading { color: var(--textmuted); }
|
||||
.gb-imagefailed { color: var(--danger, #b3261e); }
|
||||
.gb-figure figcaption { font-size: 0.8rem; color: var(--text-light); margin-top: 0.35rem; }
|
||||
|
||||
.gb-tablewrap { overflow-x: auto; margin: 0 0 1.2rem; }
|
||||
|
||||
Reference in New Issue
Block a user