nodebb-plugin-pdf-secure 1.1.0 → 1.1.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/package.json +1 -1
- package/static/lib/main.js +92 -23
- package/static/style.less +98 -81
package/package.json
CHANGED
package/static/lib/main.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
console.log('[PDF-Secure] main.js loaded');
|
|
4
4
|
|
|
5
|
-
// Main plugin logic - PDF links
|
|
5
|
+
// Main plugin logic - PDF links become inline embedded viewers
|
|
6
6
|
(async function () {
|
|
7
7
|
try {
|
|
8
8
|
var hooks = await app.require('hooks');
|
|
@@ -19,7 +19,7 @@ console.log('[PDF-Secure] main.js loaded');
|
|
|
19
19
|
function interceptPdfLinks() {
|
|
20
20
|
var postContents = document.querySelectorAll('[component="post/content"]');
|
|
21
21
|
|
|
22
|
-
postContents.forEach(function (content
|
|
22
|
+
postContents.forEach(function (content) {
|
|
23
23
|
var pdfLinks = content.querySelectorAll('a[href$=".pdf"], a[href$=".PDF"]');
|
|
24
24
|
|
|
25
25
|
pdfLinks.forEach(function (link) {
|
|
@@ -29,33 +29,102 @@ console.log('[PDF-Secure] main.js loaded');
|
|
|
29
29
|
var href = link.getAttribute('href');
|
|
30
30
|
var parts = href.split('/');
|
|
31
31
|
var filename = parts[parts.length - 1];
|
|
32
|
-
console.log('[PDF-Secure]
|
|
32
|
+
console.log('[PDF-Secure] Embedding:', filename);
|
|
33
33
|
|
|
34
|
-
// Create
|
|
34
|
+
// Create inline viewer container
|
|
35
35
|
var container = document.createElement('div');
|
|
36
|
-
container.className = 'pdf-secure-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
container.className = 'pdf-secure-embed';
|
|
37
|
+
|
|
38
|
+
// Header with filename
|
|
39
|
+
var header = document.createElement('div');
|
|
40
|
+
header.className = 'pdf-secure-embed-header';
|
|
41
|
+
header.innerHTML =
|
|
42
|
+
'<div class="pdf-secure-embed-title">' +
|
|
39
43
|
'<svg viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z" fill="currentColor"/></svg>' +
|
|
44
|
+
'<span>' + escapeHtml(decodeURIComponent(link.textContent || filename)) + '</span>' +
|
|
40
45
|
'</div>' +
|
|
41
|
-
'<div class="pdf-secure-
|
|
42
|
-
'<
|
|
43
|
-
'<
|
|
44
|
-
'</
|
|
45
|
-
'
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
'<div class="pdf-secure-embed-actions">' +
|
|
47
|
+
'<button class="pdf-secure-fullscreen-btn" title="Tam Ekran">' +
|
|
48
|
+
'<svg viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" fill="currentColor"/></svg>' +
|
|
49
|
+
'</button>' +
|
|
50
|
+
'</div>';
|
|
51
|
+
container.appendChild(header);
|
|
52
|
+
|
|
53
|
+
// Iframe for viewer
|
|
54
|
+
var iframeWrapper = document.createElement('div');
|
|
55
|
+
iframeWrapper.className = 'pdf-secure-embed-body';
|
|
56
|
+
|
|
57
|
+
var iframe = document.createElement('iframe');
|
|
58
|
+
iframe.className = 'pdf-secure-iframe';
|
|
59
|
+
iframe.src = config.relative_path + '/plugins/pdf-secure/viewer?file=' + encodeURIComponent(filename);
|
|
60
|
+
iframe.setAttribute('frameborder', '0');
|
|
61
|
+
iframe.setAttribute('allowfullscreen', 'true');
|
|
62
|
+
iframe.setAttribute('loading', 'lazy');
|
|
63
|
+
|
|
64
|
+
iframeWrapper.appendChild(iframe);
|
|
65
|
+
container.appendChild(iframeWrapper);
|
|
66
|
+
|
|
67
|
+
// Fullscreen button handler
|
|
68
|
+
header.querySelector('.pdf-secure-fullscreen-btn').addEventListener('click', function () {
|
|
69
|
+
if (iframe.requestFullscreen) {
|
|
70
|
+
iframe.requestFullscreen();
|
|
71
|
+
} else if (iframe.webkitRequestFullscreen) {
|
|
72
|
+
iframe.webkitRequestFullscreen();
|
|
73
|
+
} else if (iframe.msRequestFullscreen) {
|
|
74
|
+
iframe.msRequestFullscreen();
|
|
75
|
+
}
|
|
56
76
|
});
|
|
57
77
|
|
|
58
|
-
link
|
|
78
|
+
// Check for NodeBB upload container and replace it instead of just the link
|
|
79
|
+
var uploadContainer = link.closest('.upload-container, .uploaded-file, .attachment, [data-upload], .img-responsive');
|
|
80
|
+
var nodebbPreview = link.closest('p, div');
|
|
81
|
+
|
|
82
|
+
// Also look for sibling image/icon that NodeBB might show
|
|
83
|
+
var prevSibling = link.previousElementSibling;
|
|
84
|
+
var parentParagraph = link.parentElement;
|
|
85
|
+
|
|
86
|
+
// If the link is inside a paragraph with just the link and maybe an icon, replace the whole paragraph
|
|
87
|
+
if (parentParagraph && parentParagraph.tagName === 'P') {
|
|
88
|
+
var textContent = parentParagraph.textContent.trim();
|
|
89
|
+
var linkText = link.textContent.trim();
|
|
90
|
+
// If paragraph only contains the link text (maybe with some whitespace), replace the whole paragraph
|
|
91
|
+
if (textContent === linkText || textContent === filename || textContent === decodeURIComponent(filename)) {
|
|
92
|
+
parentParagraph.replaceWith(container);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Hide any preceding SVG or image that looks like a file icon
|
|
98
|
+
if (prevSibling && (prevSibling.tagName === 'SVG' || prevSibling.tagName === 'IMG' || prevSibling.classList.contains('file-icon'))) {
|
|
99
|
+
prevSibling.style.display = 'none';
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// If there's an upload container, replace it entirely
|
|
103
|
+
if (uploadContainer) {
|
|
104
|
+
uploadContainer.replaceWith(container);
|
|
105
|
+
} else {
|
|
106
|
+
link.replaceWith(container);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Also hide any remaining large file preview icons that NodeBB might render
|
|
112
|
+
postContents.forEach(function (content) {
|
|
113
|
+
// Hide default NodeBB file preview containers for PDFs
|
|
114
|
+
var fileIcons = content.querySelectorAll('img[src*=".pdf"], svg.file-icon, .file-preview');
|
|
115
|
+
fileIcons.forEach(function (icon) {
|
|
116
|
+
// Check if this is near a pdf-secure-embed
|
|
117
|
+
var nearEmbed = icon.closest('.pdf-secure-embed');
|
|
118
|
+
if (!nearEmbed) {
|
|
119
|
+
// Check if there's a pdf-secure-embed nearby
|
|
120
|
+
var parent = icon.parentElement;
|
|
121
|
+
if (parent) {
|
|
122
|
+
var siblingEmbed = parent.querySelector('.pdf-secure-embed');
|
|
123
|
+
if (siblingEmbed) {
|
|
124
|
+
icon.style.display = 'none';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
59
128
|
});
|
|
60
129
|
});
|
|
61
130
|
}
|
package/static/style.less
CHANGED
|
@@ -1,132 +1,149 @@
|
|
|
1
|
-
/* PDF Secure Viewer —
|
|
1
|
+
/* PDF Secure Viewer — Inline Embed Styles for NodeBB */
|
|
2
|
+
|
|
3
|
+
/* Hide NodeBB default file preview icons when PDF is embedded */
|
|
4
|
+
[component="post/content"] {
|
|
5
|
+
|
|
6
|
+
/* Hide large SVG file icons that NodeBB shows for uploaded files */
|
|
7
|
+
>p>svg[viewBox],
|
|
8
|
+
>svg[viewBox],
|
|
9
|
+
>p>img[alt*=".pdf"],
|
|
10
|
+
>img[alt*=".pdf"],
|
|
11
|
+
.file-icon,
|
|
12
|
+
.attachment-icon {
|
|
13
|
+
|
|
14
|
+
&:has(+ .pdf-secure-embed),
|
|
15
|
+
&:has(~ .pdf-secure-embed) {
|
|
16
|
+
display: none !important;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
2
20
|
|
|
3
|
-
/*
|
|
4
|
-
.pdf-secure-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
margin: 12px 0;
|
|
10
|
-
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
11
|
-
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
12
|
-
border-radius: 12px;
|
|
13
|
-
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
|
14
|
-
transition: transform 0.2s, box-shadow 0.2s;
|
|
21
|
+
/* Force hide any orphaned file icons near our embeds */
|
|
22
|
+
.pdf-secure-embed~svg,
|
|
23
|
+
.pdf-secure-embed~img[alt*=".pdf"],
|
|
24
|
+
svg:has(+ .pdf-secure-embed),
|
|
25
|
+
img[alt*=".pdf"]:has(+ .pdf-secure-embed) {
|
|
26
|
+
display: none !important;
|
|
15
27
|
}
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
29
|
+
/* Embedded PDF Container */
|
|
30
|
+
.pdf-secure-embed {
|
|
31
|
+
margin: 16px 0;
|
|
32
|
+
border-radius: 12px;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
background: #1f1f1f;
|
|
35
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
36
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
|
|
20
37
|
}
|
|
21
38
|
|
|
22
|
-
|
|
39
|
+
/* Header */
|
|
40
|
+
.pdf-secure-embed-header {
|
|
23
41
|
display: flex;
|
|
24
42
|
align-items: center;
|
|
25
|
-
justify-content:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
border-radius: 10px;
|
|
30
|
-
flex-shrink: 0;
|
|
43
|
+
justify-content: space-between;
|
|
44
|
+
padding: 10px 16px;
|
|
45
|
+
background: linear-gradient(135deg, #2d2d2d 0%, #252525 100%);
|
|
46
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
31
47
|
}
|
|
32
48
|
|
|
33
|
-
.pdf-secure-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
49
|
+
.pdf-secure-embed-title {
|
|
50
|
+
display: flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
gap: 10px;
|
|
53
|
+
color: #fff;
|
|
54
|
+
font-size: 14px;
|
|
55
|
+
font-weight: 500;
|
|
37
56
|
}
|
|
38
57
|
|
|
39
|
-
.pdf-secure-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
flex:
|
|
44
|
-
min-width: 0;
|
|
58
|
+
.pdf-secure-embed-title svg {
|
|
59
|
+
width: 20px;
|
|
60
|
+
height: 20px;
|
|
61
|
+
fill: #e81224;
|
|
62
|
+
flex-shrink: 0;
|
|
45
63
|
}
|
|
46
64
|
|
|
47
|
-
.pdf-secure-
|
|
48
|
-
font-size: 14px;
|
|
49
|
-
font-weight: 600;
|
|
50
|
-
color: #fff;
|
|
65
|
+
.pdf-secure-embed-title span {
|
|
51
66
|
white-space: nowrap;
|
|
52
67
|
overflow: hidden;
|
|
53
68
|
text-overflow: ellipsis;
|
|
69
|
+
max-width: 400px;
|
|
54
70
|
}
|
|
55
71
|
|
|
56
|
-
.pdf-secure-
|
|
57
|
-
|
|
58
|
-
|
|
72
|
+
.pdf-secure-embed-actions {
|
|
73
|
+
display: flex;
|
|
74
|
+
gap: 8px;
|
|
59
75
|
}
|
|
60
76
|
|
|
61
|
-
.pdf-secure-
|
|
77
|
+
.pdf-secure-fullscreen-btn {
|
|
62
78
|
display: flex;
|
|
63
79
|
align-items: center;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
80
|
+
justify-content: center;
|
|
81
|
+
width: 32px;
|
|
82
|
+
height: 32px;
|
|
83
|
+
background: rgba(255, 255, 255, 0.08);
|
|
67
84
|
border: none;
|
|
68
|
-
border-radius:
|
|
69
|
-
color: #fff;
|
|
70
|
-
font-size: 13px;
|
|
71
|
-
font-weight: 600;
|
|
85
|
+
border-radius: 6px;
|
|
72
86
|
cursor: pointer;
|
|
73
87
|
transition: all 0.2s;
|
|
74
|
-
flex-shrink: 0;
|
|
75
88
|
}
|
|
76
89
|
|
|
77
|
-
.pdf-secure-
|
|
78
|
-
background:
|
|
79
|
-
transform: scale(1.02);
|
|
90
|
+
.pdf-secure-fullscreen-btn:hover {
|
|
91
|
+
background: rgba(255, 255, 255, 0.15);
|
|
80
92
|
}
|
|
81
93
|
|
|
82
|
-
.pdf-secure-
|
|
83
|
-
transform: scale(0.98);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.pdf-secure-card-btn svg {
|
|
94
|
+
.pdf-secure-fullscreen-btn svg {
|
|
87
95
|
width: 18px;
|
|
88
96
|
height: 18px;
|
|
89
|
-
fill:
|
|
97
|
+
fill: #fff;
|
|
90
98
|
}
|
|
91
99
|
|
|
92
|
-
/*
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
/* Viewer Body */
|
|
101
|
+
.pdf-secure-embed-body {
|
|
102
|
+
position: relative;
|
|
103
|
+
width: 100%;
|
|
104
|
+
height: 600px;
|
|
105
|
+
background: #525659;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.pdf-secure-iframe {
|
|
109
|
+
width: 100%;
|
|
110
|
+
height: 100%;
|
|
111
|
+
border: none;
|
|
112
|
+
display: block;
|
|
113
|
+
}
|
|
98
114
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
115
|
+
/* Responsive */
|
|
116
|
+
@media (max-width: 768px) {
|
|
117
|
+
.pdf-secure-embed-body {
|
|
118
|
+
height: 450px;
|
|
102
119
|
}
|
|
103
120
|
|
|
104
|
-
.pdf-secure-
|
|
105
|
-
width:
|
|
106
|
-
height: 22px;
|
|
121
|
+
.pdf-secure-embed-title span {
|
|
122
|
+
max-width: 200px;
|
|
107
123
|
}
|
|
124
|
+
}
|
|
108
125
|
|
|
109
|
-
|
|
110
|
-
|
|
126
|
+
@media (max-width: 480px) {
|
|
127
|
+
.pdf-secure-embed-body {
|
|
128
|
+
height: 350px;
|
|
111
129
|
}
|
|
112
130
|
|
|
113
|
-
.pdf-secure-
|
|
114
|
-
padding: 8px
|
|
115
|
-
font-size: 12px;
|
|
131
|
+
.pdf-secure-embed-header {
|
|
132
|
+
padding: 8px 12px;
|
|
116
133
|
}
|
|
117
134
|
|
|
118
|
-
.pdf-secure-
|
|
119
|
-
|
|
135
|
+
.pdf-secure-embed-title {
|
|
136
|
+
font-size: 13px;
|
|
120
137
|
}
|
|
121
138
|
|
|
122
|
-
.pdf-secure-
|
|
123
|
-
|
|
139
|
+
.pdf-secure-embed-title span {
|
|
140
|
+
max-width: 150px;
|
|
124
141
|
}
|
|
125
142
|
}
|
|
126
143
|
|
|
127
|
-
/* Anti-print
|
|
144
|
+
/* Anti-print */
|
|
128
145
|
@media print {
|
|
129
|
-
.pdf-secure-
|
|
146
|
+
.pdf-secure-embed {
|
|
130
147
|
display: none !important;
|
|
131
148
|
}
|
|
132
149
|
}
|