forgepress 0.0.0 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/THIRD-PARTY-LICENSES.md +42 -0
- package/dist/_chunks/client.d.mts +2 -0
- package/dist/_chunks/config.mjs +79 -0
- package/dist/_chunks/content.mjs +733 -0
- package/dist/_chunks/error.mjs +4 -0
- package/dist/_chunks/fetch.mjs +13 -0
- package/dist/_chunks/files.mjs +32 -0
- package/dist/_chunks/libs/diff.mjs +485 -0
- package/dist/_chunks/locate.mjs +7 -0
- package/dist/_chunks/media.mjs +282 -0
- package/dist/_chunks/once.mjs +16 -0
- package/dist/_chunks/output.mjs +104 -0
- package/dist/_chunks/overlay.mjs +8 -0
- package/dist/_chunks/plugin.mjs +87 -0
- package/dist/_chunks/preview.mjs +248 -0
- package/dist/_chunks/project.d.mts +7 -0
- package/dist/_chunks/reader.mjs +19 -0
- package/dist/_chunks/reader2.mjs +797 -0
- package/dist/_chunks/references.mjs +56 -0
- package/dist/_chunks/resolve.d.mts +2 -0
- package/dist/_chunks/response.mjs +5 -0
- package/dist/_chunks/routes.mjs +9 -0
- package/dist/_chunks/serialize.mjs +82 -0
- package/dist/_chunks/settings.mjs +328 -0
- package/dist/_chunks/settings2.mjs +2 -0
- package/dist/_chunks/types.d.mts +230 -0
- package/dist/_chunks/types2.d.mts +25 -0
- package/dist/_chunks/value.mjs +139 -0
- package/dist/cli/bin.d.mts +1 -0
- package/dist/cli/bin.mjs +61 -0
- package/dist/disk/reader.d.mts +4 -0
- package/dist/disk/reader.mjs +2 -0
- package/dist/editor/index.d.mts +3 -0
- package/dist/editor/index.mjs +61951 -0
- package/dist/index.d.mts +104 -0
- package/dist/index.mjs +237 -0
- package/dist/next/preview.d.mts +1 -0
- package/dist/next/preview.mjs +3 -0
- package/dist/next/reload.d.mts +1 -0
- package/dist/next/reload.mjs +20 -0
- package/dist/next/settings.d.mts +12 -0
- package/dist/next/settings.mjs +2 -0
- package/dist/plugin/next.d.mts +11 -0
- package/dist/plugin/next.mjs +213 -0
- package/dist/plugin/nuxt.d.mts +7 -0
- package/dist/plugin/nuxt.mjs +52 -0
- package/dist/plugin/watcher.d.mts +1 -0
- package/dist/plugin/watcher.mjs +23 -0
- package/dist/preview/index.d.mts +4 -0
- package/dist/preview/index.mjs +2 -0
- package/dist/preview/react.d.mts +1 -0
- package/dist/preview/react.mjs +34 -0
- package/dist/query/fetch.d.mts +3 -0
- package/dist/query/fetch.mjs +2 -0
- package/dist/unplugin.d.mts +13 -0
- package/dist/unplugin.mjs +2 -0
- package/package.json +146 -2
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { once } from "./once.mjs";
|
|
2
|
+
import { overlayContent } from "./overlay.mjs";
|
|
3
|
+
import { errorMessage } from "./error.mjs";
|
|
4
|
+
const TAG = "forgepress-preview";
|
|
5
|
+
const HIDING = "forgepress-preview-hiding";
|
|
6
|
+
const LABELS = {
|
|
7
|
+
loading: "Loading preview…",
|
|
8
|
+
ready: "Preview",
|
|
9
|
+
failed: "Preview unavailable"
|
|
10
|
+
};
|
|
11
|
+
const STYLE = `
|
|
12
|
+
:host {
|
|
13
|
+
all: initial;
|
|
14
|
+
position: fixed;
|
|
15
|
+
left: 16px;
|
|
16
|
+
bottom: 16px;
|
|
17
|
+
z-index: 2147483647;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.badge {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
gap: 8px;
|
|
24
|
+
padding: 4px 4px 4px 12px;
|
|
25
|
+
border-radius: 999px;
|
|
26
|
+
background: #13110e;
|
|
27
|
+
color: #fffcf8;
|
|
28
|
+
font: 500 13px/20px ui-sans-serif, system-ui, sans-serif;
|
|
29
|
+
box-shadow: 0 4px 16px rgb(19 17 14 / 0.3);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.dot {
|
|
33
|
+
width: 8px;
|
|
34
|
+
height: 8px;
|
|
35
|
+
border-radius: 50%;
|
|
36
|
+
background: #ffd27a;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
[data-status="loading"] .dot {
|
|
40
|
+
animation: pulse 1s ease-in-out infinite;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
[data-status="failed"] .dot {
|
|
44
|
+
background: #f87171;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
button {
|
|
48
|
+
all: unset;
|
|
49
|
+
padding: 2px 10px;
|
|
50
|
+
border-radius: 999px;
|
|
51
|
+
color: #ffd27a;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
button:hover {
|
|
56
|
+
background: rgb(255 252 248 / 0.12);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
button:focus-visible {
|
|
60
|
+
outline: 2px solid #ffd27a;
|
|
61
|
+
outline-offset: 2px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@keyframes pulse {
|
|
65
|
+
50% {
|
|
66
|
+
opacity: 0.4;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@media (prefers-reduced-motion: reduce) {
|
|
71
|
+
[data-status="loading"] .dot {
|
|
72
|
+
animation: none;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
`;
|
|
76
|
+
function createBadge(turnOff) {
|
|
77
|
+
let host;
|
|
78
|
+
let badge;
|
|
79
|
+
let label;
|
|
80
|
+
let latest;
|
|
81
|
+
function hideInEditor() {
|
|
82
|
+
if (document.getElementById(HIDING)) return;
|
|
83
|
+
const style = document.createElement("style");
|
|
84
|
+
style.id = HIDING;
|
|
85
|
+
style.textContent = `body:has([data-forgepress-editor]) > ${TAG} { display: none !important; }`;
|
|
86
|
+
document.head.append(style);
|
|
87
|
+
}
|
|
88
|
+
function mount() {
|
|
89
|
+
hideInEditor();
|
|
90
|
+
host = document.createElement(TAG);
|
|
91
|
+
badge = document.createElement("div");
|
|
92
|
+
label = document.createElement("span");
|
|
93
|
+
const root = host.attachShadow({ mode: "open" });
|
|
94
|
+
const style = document.createElement("style");
|
|
95
|
+
const dot = document.createElement("span");
|
|
96
|
+
const button = document.createElement("button");
|
|
97
|
+
style.textContent = STYLE;
|
|
98
|
+
badge.className = "badge";
|
|
99
|
+
badge.setAttribute("role", "status");
|
|
100
|
+
dot.className = "dot";
|
|
101
|
+
button.type = "button";
|
|
102
|
+
button.textContent = "Turn off";
|
|
103
|
+
button.setAttribute("aria-label", "Turn off preview");
|
|
104
|
+
button.addEventListener("click", turnOff);
|
|
105
|
+
badge.append(dot, label, button);
|
|
106
|
+
root.append(style, badge);
|
|
107
|
+
document.body.append(host);
|
|
108
|
+
}
|
|
109
|
+
function show(state) {
|
|
110
|
+
latest = state;
|
|
111
|
+
if (!document.body) {
|
|
112
|
+
document.addEventListener("DOMContentLoaded", () => latest && show(latest), { once: true });
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (!host?.isConnected) mount();
|
|
116
|
+
badge.dataset.status = state.status;
|
|
117
|
+
label.textContent = LABELS[state.status];
|
|
118
|
+
badge.title = state.status === "failed" ? `${state.error}. The site shows published content.` : "";
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
show,
|
|
122
|
+
hide: () => {
|
|
123
|
+
latest = void 0;
|
|
124
|
+
host?.remove();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function readLocal(key) {
|
|
129
|
+
try {
|
|
130
|
+
return localStorage.getItem(key);
|
|
131
|
+
} catch {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function readLocalJson(key) {
|
|
136
|
+
const text = readLocal(key);
|
|
137
|
+
try {
|
|
138
|
+
return text ? JSON.parse(text) : void 0;
|
|
139
|
+
} catch {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function writeLocal(key, value) {
|
|
144
|
+
try {
|
|
145
|
+
if (value === void 0) localStorage.removeItem(key);
|
|
146
|
+
else localStorage.setItem(key, value);
|
|
147
|
+
} catch {}
|
|
148
|
+
}
|
|
149
|
+
const SETTINGS_KEY = "forgepress:preview";
|
|
150
|
+
const OFF_KEY = "forgepress:preview:off";
|
|
151
|
+
const CHANNEL = "forgepress:preview";
|
|
152
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
153
|
+
let version = 0;
|
|
154
|
+
let channel;
|
|
155
|
+
let listening = false;
|
|
156
|
+
function emit() {
|
|
157
|
+
version += 1;
|
|
158
|
+
for (const listener of [...listeners]) listener();
|
|
159
|
+
}
|
|
160
|
+
function listen() {
|
|
161
|
+
if (listening || typeof window === "undefined") return;
|
|
162
|
+
listening = true;
|
|
163
|
+
window.addEventListener("storage", (event) => {
|
|
164
|
+
if (event.key === null || event.key === SETTINGS_KEY || event.key === OFF_KEY) emit();
|
|
165
|
+
});
|
|
166
|
+
if (typeof BroadcastChannel !== "undefined") {
|
|
167
|
+
channel = new BroadcastChannel(CHANNEL);
|
|
168
|
+
channel.addEventListener("message", emit);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function previewSettings() {
|
|
172
|
+
return readLocalJson(SETTINGS_KEY);
|
|
173
|
+
}
|
|
174
|
+
function previewEnabled() {
|
|
175
|
+
return readLocal(OFF_KEY) === null;
|
|
176
|
+
}
|
|
177
|
+
function previewing() {
|
|
178
|
+
return typeof window !== "undefined" && previewEnabled() && readLocal(SETTINGS_KEY) !== null;
|
|
179
|
+
}
|
|
180
|
+
function previewVersion() {
|
|
181
|
+
return version;
|
|
182
|
+
}
|
|
183
|
+
function onPreviewChange(listener) {
|
|
184
|
+
listen();
|
|
185
|
+
listeners.add(listener);
|
|
186
|
+
return () => {
|
|
187
|
+
listeners.delete(listener);
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function setPreviewEnabled(enabled) {
|
|
191
|
+
if (previewEnabled() === enabled) return;
|
|
192
|
+
writeLocal(OFF_KEY, enabled ? void 0 : "1");
|
|
193
|
+
emit();
|
|
194
|
+
}
|
|
195
|
+
let enabled = false;
|
|
196
|
+
let snapshot;
|
|
197
|
+
let selected;
|
|
198
|
+
const badge = createBadge(() => setPreviewEnabled(false));
|
|
199
|
+
function readerFor(settings) {
|
|
200
|
+
const key = JSON.stringify(settings);
|
|
201
|
+
if (selected?.key !== key) selected = {
|
|
202
|
+
key,
|
|
203
|
+
reader: once(() => import("./reader2.mjs").then((module) => module.createPreviewReader(settings)))
|
|
204
|
+
};
|
|
205
|
+
return selected.reader();
|
|
206
|
+
}
|
|
207
|
+
function load() {
|
|
208
|
+
const version = previewVersion();
|
|
209
|
+
if (snapshot?.version === version) return snapshot.files;
|
|
210
|
+
const settings = previewSettings();
|
|
211
|
+
const current = {
|
|
212
|
+
version,
|
|
213
|
+
files: (settings ? readerFor(settings).then((reader) => reader.build()) : Promise.reject(/* @__PURE__ */ new Error("[forgepress] sign in to the editor to preview unpublished content"))).then((files) => {
|
|
214
|
+
if (snapshot === current) badge.show({ status: "ready" });
|
|
215
|
+
return files;
|
|
216
|
+
}, (cause) => {
|
|
217
|
+
if (snapshot === current) badge.show({
|
|
218
|
+
status: "failed",
|
|
219
|
+
error: errorMessage(cause)
|
|
220
|
+
});
|
|
221
|
+
})
|
|
222
|
+
};
|
|
223
|
+
snapshot = current;
|
|
224
|
+
badge.show({ status: "loading" });
|
|
225
|
+
return current.files;
|
|
226
|
+
}
|
|
227
|
+
async function read(path, base) {
|
|
228
|
+
if (!previewing()) return base(path);
|
|
229
|
+
const files = await load();
|
|
230
|
+
if (!files) return base(path);
|
|
231
|
+
const text = files.get(path);
|
|
232
|
+
return text === void 0 ? void 0 : JSON.parse(text);
|
|
233
|
+
}
|
|
234
|
+
function refresh() {
|
|
235
|
+
if (previewing()) load();
|
|
236
|
+
else badge.hide();
|
|
237
|
+
}
|
|
238
|
+
function enablePreview() {
|
|
239
|
+
if (typeof window === "undefined") return false;
|
|
240
|
+
if (!enabled) {
|
|
241
|
+
enabled = true;
|
|
242
|
+
overlayContent(read);
|
|
243
|
+
onPreviewChange(refresh);
|
|
244
|
+
refresh();
|
|
245
|
+
}
|
|
246
|
+
return previewing();
|
|
247
|
+
}
|
|
248
|
+
export { enablePreview, onPreviewChange, previewing };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { once } from "./once.mjs";
|
|
2
|
+
import { readText } from "./files.mjs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
const OUTPUT_VARIABLE = "FORGEPRESS_OUTPUT";
|
|
6
|
+
function diskReader(dir) {
|
|
7
|
+
return async (path) => {
|
|
8
|
+
const text = await readText(join(await dir(), path));
|
|
9
|
+
return text === void 0 ? void 0 : JSON.parse(text);
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
async function locate() {
|
|
13
|
+
const known = process.env[OUTPUT_VARIABLE];
|
|
14
|
+
if (known) return known;
|
|
15
|
+
const { locateOutput } = await import("./locate.mjs");
|
|
16
|
+
return locateOutput(process.cwd());
|
|
17
|
+
}
|
|
18
|
+
const reader = diskReader(once(locate));
|
|
19
|
+
export { OUTPUT_VARIABLE, diskReader, reader };
|