domma-cms 0.88.1 → 0.89.0

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.
@@ -0,0 +1,224 @@
1
+ <!-- SEO. Bound with M.applyBindings - admin/views/seo.js inserts the item templates (the router renders a
2
+ templateUrl through _.render, eating any {{…}}). Refresh and Settings are banner actions. -->
3
+ <div class="sox">
4
+ <p class="sox-note is-bad" data-bind-hidden="!error.value" data-bind-text="error.value"></p>
5
+ <p class="sox-note is-warn" data-bind-hidden="hooksOk.value">This version of Domma CMS cannot take SEO's changes to the sitemap, robots.txt and page tags - they are core's own until it is updated (0.89 or later). The audit, the editor and redirects work.</p>
6
+
7
+ <nav class="sox-tabs" role="tablist" aria-label="SEO">
8
+ <button type="button" role="tab" data-on-click="tab_overview" data-bind-class="tab.value === 'overview' && 'is-on'"><span data-icon="search" data-icon-size="14"></span> Pages <small class="sox-count" data-bind-hidden="!attention.value" data-bind-text="attention.value"></small></button>
9
+ <button type="button" role="tab" data-on-click="tab_redirects" data-bind-class="tab.value === 'redirects' && 'is-on'"><span data-icon="corner-up-right" data-icon-size="14"></span> Redirects <small class="sox-count" data-bind-hidden="!ruleCount.value" data-bind-text="ruleCount.value"></small></button>
10
+ <button type="button" role="tab" data-on-click="tab_sitemap" data-bind-class="tab.value === 'sitemap' && 'is-on'"><span data-icon="map" data-icon-size="14"></span> Sitemap</button>
11
+ <span class="sox-ext-tabs"></span>
12
+ </nav>
13
+
14
+ <!-- Pages: the audit -->
15
+ <section class="sox-panel" data-bind-hidden="tab.value !== 'overview'" data-bind-class="busy.value && 'is-busy'">
16
+ <div class="sox-tiles">
17
+ <div class="sox-card sox-tile sox-score" data-bind-data-tone="scoreTone.value">
18
+ <small>Score <span data-help="The average of every page's score. A page's score is the share of its checks that pass - a check that could be better counts half; one for information only is left out. Pages hidden from search engines are not counted."></span></small>
19
+ <strong data-bind-text="scoreText.value">—</strong>
20
+ <span class="sox-bar"><span data-bind-style-width="scoreWidth.value"></span></span>
21
+ </div>
22
+ <div class="sox-card sox-tile"><small>Pages checked <span data-help="Every address in the sitemap - your pages and what plugins serve, such as blog posts - plus published pages hidden from search engines."></span></small><strong data-bind-text="ov.value.pages">—</strong></div>
23
+ <div class="sox-card sox-tile"><small>Need attention <span data-help="Pages with at least one failing check, or that could not be fetched."></span></small><strong data-bind-text="ov.value.failing">—</strong></div>
24
+ <div class="sox-card sox-tile"><small>Duplicates <span data-help="Titles or descriptions used on more than one page. Each page should say what makes it different - search engines may show only one of them."></span></small><strong data-bind-text="ov.value.duplicates">—</strong></div>
25
+ <div class="sox-card sox-tile"><small>Redirects <span data-help="Old addresses sent on to new ones. See the Redirects tab."></span></small><strong data-bind-text="ov.value.redirects">—</strong></div>
26
+ </div>
27
+
28
+ <div class="sox-card" data-bind-hidden="!siteRows.value.length">
29
+ <div class="sox-card-title">Across the site <span data-help="Problems that no single page shows: the same title or description on several pages, and site-wide settings worth a look."></span></div>
30
+ <div class="sox-list sox-site" data-each="siteRows.value key=id"></div>
31
+ </div>
32
+
33
+ <div class="sox-toolbar">
34
+ <div class="sox-seg" role="group" aria-label="Which pages">
35
+ <button type="button" data-on-click="show_all" data-bind-class="show.value === 'all' && 'is-on'">All</button>
36
+ <button type="button" data-on-click="show_problems" data-bind-class="show.value === 'problems' && 'is-on'">Need attention</button>
37
+ <button type="button" data-on-click="show_hidden" data-bind-class="show.value === 'hidden' && 'is-on'">Hidden</button>
38
+ </div>
39
+ <select class="form-input sox-select" aria-label="Where from" data-model="source.value" data-bind-hidden="sourceOptions.value.length < 2"></select>
40
+ <input type="search" class="form-input sox-search" placeholder="Address, title…" aria-label="Search pages" data-model="query.value">
41
+ <span class="sox-spacer"></span>
42
+ <small class="sox-muted" data-bind-text="asOf.value"></small>
43
+ <span data-help-title="Pages" data-help="Click a page to see its search result and share card as they will look, what could be better, and to change its title, description, focus keyphrase and share image. Right-click (or ⋮) for more."></span>
44
+ </div>
45
+ <div class="sox-card sox-flush">
46
+ <p class="sox-note sox-pad" data-bind-hidden="pageRows.value.length" data-bind-text="pagesEmpty.value"></p>
47
+ <div class="sox-list sox-pages" data-each="pageRows.value key=id"></div>
48
+ </div>
49
+ </section>
50
+
51
+ <!-- Redirects -->
52
+ <section class="sox-panel" data-bind-hidden="tab.value !== 'redirects'">
53
+ <div class="sox-card">
54
+ <div class="sox-card-title">Add a redirect
55
+ <span data-help-title="Redirects" data-help="Sends an old address to a new one, so links and search results keep working. 301 is permanent (search engines move the old page's standing to the new one); 302 is for a while; 410 says the page is gone for good. End the old address with /* to move everything under it: /news/* to /blog/* sends /news/hello to /blog/hello."></span>
56
+ <span class="sox-spacer"></span>
57
+ <button type="button" class="btn btn-xs btn-ghost" data-on-click="importCsv" data-bind-disabled="!canManage.value"><span data-icon="upload" data-icon-size="12"></span> Import</button>
58
+ <button type="button" class="btn btn-xs btn-ghost" data-on-click="exportRules"><span data-icon="download" data-icon-size="12"></span> CSV</button>
59
+ </div>
60
+ <form class="sox-add" data-on-submit="addRule" data-bind-hidden="!canManage.value">
61
+ <input type="text" class="form-input sox-mono" placeholder="/old-address" aria-label="From" data-model="newFrom.value">
62
+ <span class="sox-arrow" aria-hidden="true">→</span>
63
+ <input type="text" class="form-input sox-mono" placeholder="/new-address or https://…" aria-label="To" data-model="newTo.value" data-bind-disabled="newCode.value === '410'">
64
+ <select class="form-input sox-code" aria-label="Kind" data-model="newCode.value">
65
+ <option value="301">301 moved</option><option value="302">302 for now</option><option value="307">307 for now, same method</option><option value="308">308 moved, same method</option><option value="410">410 gone</option>
66
+ </select>
67
+ <button type="submit" class="btn btn-sm btn-primary" data-bind-disabled="!newFrom.value"><span data-icon="plus" data-icon-size="12"></span> Add</button>
68
+ </form>
69
+ <small class="sox-muted" data-bind-text="renameText.value"></small>
70
+ </div>
71
+ <p class="sox-note is-warn" data-bind-hidden="!chainText.value" data-bind-text="chainText.value"></p>
72
+ <div class="sox-toolbar">
73
+ <input type="search" class="form-input sox-search" placeholder="Address…" aria-label="Search redirects" data-model="ruleQuery.value">
74
+ <span class="sox-spacer"></span>
75
+ <small class="sox-muted" data-bind-text="ruleText.value"></small>
76
+ </div>
77
+ <div class="sox-card sox-flush">
78
+ <p class="sox-note sox-pad" data-bind-hidden="ruleRows.value.length" data-bind-text="rulesEmpty.value"></p>
79
+ <div class="sox-list sox-rules" data-each="ruleRows.value key=id"></div>
80
+ </div>
81
+ </section>
82
+
83
+ <!-- Sitemap -->
84
+ <section class="sox-panel" data-bind-hidden="tab.value !== 'sitemap'">
85
+ <div class="sox-grid2">
86
+ <div class="sox-card">
87
+ <div class="sox-card-title">What it lists
88
+ <span data-help="Your pages, and what each plugin serves. Switch a source off to leave all of it out; leave out single addresses in the settings, or hide one page from search engines in its editor."></span>
89
+ <span class="sox-spacer"></span>
90
+ <a class="btn btn-xs btn-ghost" href="/sitemap.xml" target="_blank" rel="noopener"><span data-icon="external-link" data-icon-size="12"></span> sitemap.xml</a>
91
+ </div>
92
+ <div class="sox-list sox-sources" data-each="sourceRows.value key=id"></div>
93
+ </div>
94
+ <div class="sox-card">
95
+ <div class="sox-card-title">robots.txt
96
+ <span data-help="What crawlers are asked to leave alone, and where the sitemap is. Add rules in the settings - or ask every search engine to stay away while a site is not ready."></span>
97
+ <span class="sox-spacer"></span>
98
+ <a class="btn btn-xs btn-ghost" href="/robots.txt" target="_blank" rel="noopener"><span data-icon="external-link" data-icon-size="12"></span> robots.txt</a>
99
+ </div>
100
+ <pre class="sox-code" data-bind-text="robots.value"></pre>
101
+ </div>
102
+ </div>
103
+ <div class="sox-toolbar">
104
+ <div class="sox-seg" role="group" aria-label="Which addresses">
105
+ <button type="button" data-on-click="sm_in" data-bind-class="smShow.value === 'in' && 'is-on'">Listed</button>
106
+ <button type="button" data-on-click="sm_out" data-bind-class="smShow.value === 'out' && 'is-on'">Left out</button>
107
+ </div>
108
+ <input type="search" class="form-input sox-search" placeholder="Address…" aria-label="Search the sitemap" data-model="smQuery.value">
109
+ <span class="sox-spacer"></span>
110
+ <small class="sox-muted" data-bind-text="smText.value"></small>
111
+ </div>
112
+ <div class="sox-card sox-flush">
113
+ <p class="sox-note sox-pad" data-bind-hidden="smRows.value.length" data-bind-text="smEmpty.value"></p>
114
+ <div class="sox-list sox-entries" data-each="smRows.value key=id"></div>
115
+ </div>
116
+ </section>
117
+
118
+ <section class="sox-ext" data-bind-hidden="!extOn.value"><div class="sox-panel sox-ext-body"></div></section>
119
+ </div>
120
+
121
+ <style>
122
+ .sox { display: flex; flex-direction: column; gap: 1rem; }
123
+ .sox [hidden] { display: none !important; }
124
+ .sox-panel { display: flex; flex-direction: column; gap: 1rem; transition: opacity .2s; min-width: 0; }
125
+ .sox-panel.is-busy { opacity: .6; }
126
+ .sox-note { margin: 0; color: var(--dm-text-muted); font-size: var(--dm-text-sm); }
127
+ .sox-note.is-bad, .sox-note.is-warn { padding: .6rem .8rem; border-radius: var(--dm-radius-md); }
128
+ .sox-note.is-bad { background: color-mix(in srgb, var(--dm-danger) 14%, transparent); color: var(--dm-danger); }
129
+ .sox-note.is-warn { background: color-mix(in srgb, var(--dm-warning) 14%, transparent); color: var(--dm-text); }
130
+ .sox-pad { padding: .8rem .9rem; }
131
+ .sox-tabs { display: flex; gap: .15rem; border-bottom: 1px solid var(--dm-border); overflow-x: auto; }
132
+ .sox-ext-tabs { display: contents; }
133
+ .sox-tabs button { border: 0; background: none; color: var(--dm-text-muted); font: inherit; font-size: var(--dm-text-sm); padding: .45rem .75rem; cursor: pointer;
134
+ border-bottom: 2px solid transparent; margin-bottom: -1px; display: inline-flex; align-items: center; gap: .35rem; white-space: nowrap; }
135
+ .sox-tabs button:hover { color: var(--dm-text); }
136
+ .sox-tabs button.is-on { color: var(--dm-text); border-bottom-color: var(--dm-primary); font-weight: 600; }
137
+ .sox-pro { font-size: .65rem; font-weight: 700; letter-spacing: .04em; padding: 0 .3rem; border-radius: var(--dm-radius-sm); background: color-mix(in srgb, var(--dm-primary) 16%, transparent); color: var(--dm-primary); }
138
+ .sox-count { font-size: var(--dm-text-xs); padding: 0 .4rem; border-radius: 999px; background: color-mix(in srgb, var(--dm-text) 10%, transparent); }
139
+ .sox-card { border: 1px solid var(--dm-border); border-radius: var(--dm-radius-md); padding: .75rem .9rem; display: flex; flex-direction: column; gap: .6rem; min-width: 0; }
140
+ .sox-flush { padding: 0; }
141
+ .sox-card-title { display: flex; align-items: center; gap: .4rem; font-weight: 600; flex-wrap: wrap; }
142
+ .sox-spacer { flex: 1; }
143
+ .sox-muted { color: var(--dm-text-muted); font-weight: 400; font-size: var(--dm-text-xs); }
144
+ .sox-mono { font-family: var(--dm-font-mono, monospace); }
145
+ .sox-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 9.5rem), 1fr)); gap: 1rem; }
146
+ .sox-tile { gap: .15rem; }
147
+ .sox-tile small { color: var(--dm-text-muted); font-size: var(--dm-text-sm); display: inline-flex; align-items: center; gap: .3rem; }
148
+ .sox-tile strong { font-size: var(--dm-text-2xl, 1.5rem); line-height: 1.15; font-weight: 600; }
149
+ .sox-bar { display: block; height: .35rem; border-radius: 999px; background: color-mix(in srgb, var(--dm-text) 10%, transparent); overflow: hidden; margin-top: .3rem; }
150
+ .sox-bar span { display: block; height: 100%; border-radius: inherit; background: var(--dm-primary); }
151
+ .sox-score[data-tone="good"] .sox-bar span { background: var(--dm-success); }
152
+ .sox-score[data-tone="poor"] .sox-bar span { background: var(--dm-warning); }
153
+ .sox-score[data-tone="bad"] .sox-bar span { background: var(--dm-danger); }
154
+ .sox-grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); gap: 1rem; }
155
+ .sox-toolbar { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
156
+ .sox-seg { display: inline-flex; border: 1px solid var(--dm-border); border-radius: var(--dm-radius-md); overflow: hidden; }
157
+ .sox-seg button { border: 0; background: none; color: var(--dm-text); padding: .3rem .7rem; cursor: pointer; font: inherit; font-size: var(--dm-text-sm); }
158
+ .sox-seg button + button { border-left: 1px solid var(--dm-border); }
159
+ .sox-seg button.is-on { background: var(--dm-primary); color: var(--dm-primary-text); }
160
+ .sox-select, .sox-search { width: auto; padding: .25rem .5rem; font-size: var(--dm-text-sm); }
161
+ .sox-search { flex: 0 1 15rem; }
162
+ .sox-list { display: flex; flex-direction: column; max-height: 36rem; overflow-y: auto; }
163
+ .sox-row { display: grid; align-items: center; gap: .6rem; padding: .45rem .8rem; border-bottom: 1px solid var(--dm-border); font-size: var(--dm-text-sm); cursor: default; min-width: 0; }
164
+ .sox-row:last-child { border-bottom: 0; }
165
+ .sox-row:hover, .sox-row:focus-visible { background: var(--dm-table-hover-bg, color-mix(in srgb, var(--dm-text) 6%, transparent)); outline: none; }
166
+ .sox-pages .sox-row { grid-template-columns: 3.2rem minmax(8rem, 1fr) minmax(8rem, 1.3fr) minmax(8rem, 1.4fr) 1.5rem; cursor: pointer; }
167
+ .sox-rules .sox-row { grid-template-columns: minmax(8rem, 1fr) 1rem minmax(8rem, 1.2fr) 4.2rem 5.5rem 1.5rem; }
168
+ .sox-entries .sox-row { grid-template-columns: minmax(10rem, 1.5fr) 7rem minmax(6rem, 1fr) 1.5rem; }
169
+ .sox-sources .sox-row, .sox-site .sox-row { grid-template-columns: minmax(0, 1fr) auto 1.5rem; padding: .45rem .3rem; }
170
+ .sox-cell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
171
+ .sox-cell small { display: block; color: var(--dm-text-muted); font-size: var(--dm-text-xs); overflow: hidden; text-overflow: ellipsis; }
172
+ .sox-pill { display: inline-flex; align-items: center; justify-content: center; justify-self: start; font-size: var(--dm-text-xs); font-weight: 600; padding: .05rem .5rem; border-radius: 999px; min-width: 2.4rem;
173
+ color: var(--dm-text-muted); background: color-mix(in srgb, var(--dm-text) 8%, transparent); }
174
+ .sox-pill[data-tone="good"] { color: var(--dm-success); background: color-mix(in srgb, var(--dm-success) 14%, transparent); }
175
+ .sox-pill[data-tone="poor"] { color: var(--dm-warning); background: color-mix(in srgb, var(--dm-warning) 16%, transparent); }
176
+ .sox-pill[data-tone="bad"] { color: var(--dm-danger); background: color-mix(in srgb, var(--dm-danger) 12%, transparent); }
177
+ .sox-pill[data-tone="info"] { color: var(--dm-info); background: color-mix(in srgb, var(--dm-info) 14%, transparent); }
178
+ .sox-arrow { color: var(--dm-text-muted); text-align: center; }
179
+ .sox-kebab { border: 0; background: none; cursor: pointer; font-size: var(--dm-text-lg); line-height: 1; color: var(--dm-text-muted); border-radius: var(--dm-radius-sm); padding: 0 .25rem; }
180
+ .sox-kebab:hover { color: var(--dm-primary); }
181
+ .sox-add { display: flex; gap: .4rem; flex-wrap: wrap; align-items: center; margin: 0; }
182
+ .sox-add .form-input { width: auto; flex: 1 1 11rem; padding: .25rem .5rem; font-size: var(--dm-text-sm); }
183
+ .sox-add .sox-code { flex: 0 1 11rem; }
184
+ .sox-code { font-family: var(--dm-font-mono, monospace); font-size: var(--dm-text-xs); background: color-mix(in srgb, var(--dm-text) 7%, transparent); padding: .5rem .65rem; border-radius: var(--dm-radius-sm); white-space: pre-wrap; margin: 0; max-height: 16rem; overflow: auto; }
185
+ /* the page editor (slideover) */
186
+ .sox-form { display: flex; flex-direction: column; gap: 1.1rem; padding-bottom: 1rem; }
187
+ .sox-form h4 { margin: 0 0 .5rem; font-size: var(--dm-text-base); display: flex; align-items: center; gap: .5rem; }
188
+ .sox-form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: .7rem 1rem; }
189
+ .sox-wide { grid-column: 1 / -1; }
190
+ .sox-err { color: var(--dm-danger); font-size: var(--dm-text-xs); }
191
+ .sox-actions { display: flex; align-items: center; gap: .5rem; border-top: 1px solid var(--dm-border); padding-top: .8rem; }
192
+ .sox-meter { display: flex; align-items: center; gap: .5rem; font-size: var(--dm-text-xs); color: var(--dm-text-muted); margin-top: .25rem; }
193
+ .sox-meter .sox-bar { flex: 1; margin: 0; }
194
+ .sox-meter[data-tone="good"] .sox-bar span { background: var(--dm-success); }
195
+ .sox-meter[data-tone="poor"] .sox-bar span { background: var(--dm-warning); }
196
+ .sox-meter[data-tone="bad"] .sox-bar span { background: var(--dm-danger); }
197
+ .sox-serp { border: 1px solid var(--dm-border); border-radius: var(--dm-radius-md); padding: .8rem 1rem; background: #fff; color: #202124; font-family: Arial, sans-serif; }
198
+ .sox-serp-crumbs { font-size: 12px; color: #4d5156; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
199
+ .sox-serp-title { font-size: 20px; line-height: 1.3; color: #1a0dab; margin: .15rem 0 .2rem; overflow-wrap: anywhere; }
200
+ .sox-serp-desc { font-size: 14px; line-height: 1.58; color: #4d5156; overflow-wrap: anywhere; }
201
+ .sox-share { border: 1px solid var(--dm-border); border-radius: var(--dm-radius-md); overflow: hidden; max-width: 30rem; background: var(--dm-surface, var(--dm-bg)); }
202
+ .sox-share-img { aspect-ratio: 1.91 / 1; background: color-mix(in srgb, var(--dm-text) 8%, transparent) center / cover no-repeat; display: flex; align-items: center; justify-content: center; color: var(--dm-text-muted); font-size: var(--dm-text-sm); }
203
+ .sox-share-body { padding: .55rem .75rem; display: flex; flex-direction: column; gap: .15rem; }
204
+ .sox-share-body small { text-transform: uppercase; font-size: var(--dm-text-xs); color: var(--dm-text-muted); }
205
+ .sox-share-body strong { font-size: var(--dm-text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
206
+ .sox-share-body span { font-size: var(--dm-text-xs); color: var(--dm-text-muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
207
+ .sox-checks { display: flex; flex-direction: column; }
208
+ .sox-group { font-size: var(--dm-text-xs); text-transform: uppercase; letter-spacing: .05em; color: var(--dm-text-muted); padding: .6rem .1rem .2rem; font-weight: 600; }
209
+ .sox-check { display: grid; grid-template-columns: 1.5rem minmax(0, 1fr); gap: .5rem; align-items: start; padding: .4rem .1rem; border-bottom: 1px solid var(--dm-border); }
210
+ .sox-status { display: inline-flex; align-items: center; justify-content: center; width: 1.3rem; height: 1.3rem; border-radius: 50%; font-size: .72rem; font-weight: 700; margin-top: .05rem; }
211
+ .sox-status[data-status="pass"] { color: var(--dm-success); background: color-mix(in srgb, var(--dm-success) 14%, transparent); }
212
+ .sox-status[data-status="warn"] { color: var(--dm-warning); background: color-mix(in srgb, var(--dm-warning) 16%, transparent); }
213
+ .sox-status[data-status="fail"] { color: var(--dm-danger); background: color-mix(in srgb, var(--dm-danger) 14%, transparent); }
214
+ .sox-status[data-status="info"] { color: var(--dm-text-muted); background: color-mix(in srgb, var(--dm-text) 8%, transparent); }
215
+ .sox-check-main { display: flex; flex-direction: column; gap: .1rem; min-width: 0; font-size: var(--dm-text-sm); }
216
+ .sox-check-main small { color: var(--dm-text-muted); font-size: var(--dm-text-xs); overflow-wrap: anywhere; }
217
+ .sox-previews { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); gap: 1rem; align-items: start; }
218
+ @media (max-width: 720px) {
219
+ .sox-pages .sox-row { grid-template-columns: 3.2rem minmax(0, 1fr) 1.5rem; }
220
+ .sox-rules .sox-row { grid-template-columns: minmax(0, 1fr) 1rem minmax(0, 1fr) 1.5rem; }
221
+ .sox-entries .sox-row { grid-template-columns: minmax(0, 1fr) 1.5rem; }
222
+ .sox-hide-sm { display: none; }
223
+ }
224
+ </style>