diff --git a/api/ajax_pastes.php b/api/ajax_pastes.php
index 226ad4a..db81e0d 100644
--- a/api/ajax_pastes.php
+++ b/api/ajax_pastes.php
@@ -11,7 +11,16 @@ $pastes = Paste::with([
'tags' => function($query) {
$query->select('tags.id', 'name', 'slug');
}
-])->select(['id', 'user_id', 'title'])->get();
+])->select(['id', 'user_id', 'title']);
+
+if (!empty($_GET['q']) && is_string($_GET['q'])) {
+ $tags = explode(',', $_GET['q']);
+ $pastes = $pastes->whereHas('tags', function($query) use ($tags) {
+ $query->where('name', $tags);
+ });
+}
+
+$pastes = $pastes->get();
header('Content-Type: application/json; charset=UTF-8');
diff --git a/archive.php b/archive.php
index 9248616..e8980e1 100644
--- a/archive.php
+++ b/archive.php
@@ -15,4 +15,5 @@ updatePageViews($conn);
// Theme
$page_template = 'archive';
$page_title = 'Pastes Archive';
+array_push($script_bundles, 'archive');
require_once('theme/' . $default_theme . '/common.php');
diff --git a/assets/bundle/bundle.js b/assets/bundle/bundle.js
deleted file mode 100644
index 5556f4a..0000000
--- a/assets/bundle/bundle.js
+++ /dev/null
@@ -1,354 +0,0 @@
-const $ = function(selector) {
- return document.querySelector(selector);
-};
-
-const $$ = function(selector) {
- return document.querySelectorAll(selector) || [];
-};
-
-const makeEl = function(html) {
- const template = document.createElement('template');
-
- template.innerHTML = html.trim();
-
- return template.content.firstChild;
-};
-
-const clearEl = function(el) {
- while (el.firstChild) {
- el.removeChild(el.firstChild);
- }
-};
-
-const toggleEl = function(el) {
- if (el.classList.contains('is-hidden')) {
- el.classList.remove('is-hidden');
- } else {
- el.classList.add('is-hidden');
- }
-};
-
-const escape = function(unsafe) {
- return unsafe
- .replace(/&/g, "&")
- .replace(//g, ">")
- .replace(/"/g, """)
- .replace(/'/g, "'");
-};
-
-class TagsInput {
- constructor(element, options = {}) {
- this.element = element;
- this.tags = [];
- this.options = options;
-
- this.maxTags = options.maxTags || 10;
- this.inputNode = null;
- this.containerNode = null;
- }
-
- attach() {
- this.element.style.display = 'none';
-
- this.containerNode = makeEl('
');
- this.inputNode = makeEl('');
- this.containerNode.appendChild(this.inputNode);
-
- this.element.parentNode.insertBefore(this.containerNode, this.element.nextSibling);
-
- /* Load existing tags from input */
- if (this.element.value) {
- for (const tag of this.element.value.split(',')) {
- this.addTag(tag);
- }
- }
-
- /* Handle addition and removal of tags via key-presses */
- this.containerNode.addEventListener('keydown', this._handleInputKeyUp.bind(this));
-
- /* Handle deletions by clicking the delete button */
- this.containerNode.addEventListener('click', this._handleContainerClick.bind(this));
- }
-
- detach() {
- this.tags.clear();
- this.containerNode.remove();
- this.element.style.display = 'inline-block';
- }
-
- updateHiddenInputValue() {
- this.element.value = this.tags.join(',');
- }
-
- deleteTagNode(node) {
- this.tags.splice(this.tags.indexOf(node.dataset.value.toLowerCase()), 1);
- node.remove();
-
- /* Below the limit? Make sure the input is enabled. */
- if (this.tags.length < this.maxTags) {
- this.inputNode.disabled = false;
- }
- }
-
- addTag(tagValue) {
- tagValue = tagValue.trim();
-
- /* Tag value is probably not empty and we don't already have the same tag. */
- if (tagValue !== '' && this.tags.indexOf(tagValue.toLowerCase()) === -1) {
- this.tags.push(tagValue.toLowerCase());
-
- this.inputNode.parentNode.insertBefore(
- makeEl('' + escape(tagValue) + ''),
- this.inputNode
- );
-
- /* Too many tags, disable the input for now. */
- if (this.tags.length >= this.maxTags) {
- this.inputNode.disabled = true;
- }
- }
- }
-
- _handleInputKeyUp(evt) {
- let tagValue = this.inputNode.value;
-
- if (evt.key === 'Backspace' && tagValue === '') {
- // Remove the child
- if (this.inputNode.previousSibling) {
- this.deleteTagNode(this.inputNode.previousSibling);
-
- this.updateHiddenInputValue();
- }
- } else if (evt.key === ',') {
- this.addTag(tagValue);
-
- this.inputNode.value = '';
- this.updateHiddenInputValue();
-
- evt.preventDefault();
- }
- }
-
- _handleContainerClick(evt) {
- if (evt.target && evt.target.classList.contains('delete')) {
- this.deleteTagNode(evt.target.closest('.tag'));
- this.updateHiddenInputValue();
- }
- }
-}
-
-class SimplePaginator {
- constructor(element) {
- this.element = element;
- }
-
- attach(pageCallback) {
- this.element.addEventListener('click', evt => {
- if (evt.target && evt.target.classList.contains('paginator__button')) {
- pageCallback(+evt.target.dataset.page);
- }
- });
- }
-
- update(totalRecords, perPage, currentPage) {
- clearEl(this.element);
-
- /* First and last page in existence */
- const firstPage = 0;
- const lastPage = Math.floor(totalRecords / perPage); // ish?
- const numPagesToShow = 2;
-
- /* First and last page the main paginator will show */
- const firstPageShow = (currentPage - firstPage) < numPagesToShow ? firstPage : ((currentPage - numPagesToShow < 0) ? currentPage : currentPage - numPagesToShow);
- const lastPageShow = (firstPageShow + numPagesToShow) > lastPage ? lastPage : (firstPageShow + numPagesToShow + numPagesToShow);
-
- /* Whether to show the first and last pages in existence at the ends of the paginator */
- const showFirstPage = (Math.abs(firstPage - currentPage)) > (numPagesToShow);
- const showLastPage = (Math.abs(lastPage - currentPage)) > (numPagesToShow);
-
-
- const prevButtonDisabled = currentPage === firstPage ? 'disabled' : '';
-
- /* Previous button */
- this.element.appendChild(makeEl(
- `Previous`
- ));
-
- /* First page button */
- if (showFirstPage) {
- this.element.appendChild(makeEl(
- `${firstPage}`
- ));
- this.element.appendChild(makeEl(`…`));
- }
-
- /* "window" buttons */
- for (let i = firstPageShow; i <= lastPageShow; i++) {
- const selected = (i === currentPage ? 'paginator__button--selected' : '');
- this.element.appendChild(makeEl(
- `${i}`
- ));
- }
-
- /* Last page button */
- if (showLastPage) {
- this.element.appendChild(makeEl(`…`));
- this.element.appendChild(makeEl(
- `${lastPage}`
- ));
- }
-
- const nextButtonDisabled = currentPage === lastPage ? 'disabled' : '';
- /* Next button */
- this.element.appendChild(makeEl(
- `Next`
- ));
- }
-}
-
-class DataTable {
- constructor(element, options) {
- this.element = element;
- this.container = element.parentElement;
- this.options = options;
-
- this.ajaxCallback = options.ajaxCallback;
- this.data = [];
-
- this.totalRecords = -1;
- this.perPage = 20;
- this.currentPage = 0;
-
- this.paginator = new SimplePaginator(this.container.querySelector('.paginator'));
-
- }
-
- attach() {
- this.paginator.attach(this._updatePage.bind(this));
- this._loadEntries();
- }
-
- /* Load the requested data from the server, and when done, update the DOM. */
- _loadEntries() {
- new Promise(this.ajaxCallback)
- .then(this._updateEntries.bind(this));
- }
-
- /* Update the DOM to reflect the current state of the data we have loaded */
- _updateEntries(data) {
- this.data = data.data;
- this.totalRecords = this.data.length;
-
- const bodyElement = this.element.querySelector('tbody');
- clearEl(bodyElement);
-
- const firstIndex = (this.perPage * this.currentPage);
- const lastIndex = (firstIndex + this.perPage) > this.totalRecords ? this.totalRecords : (firstIndex + this.perPage);
-
-
- for (let i = firstIndex; i < lastIndex; i++) {
- const rowElem = makeEl(this.options.rowCallback(this.data[i]));
- rowElem.classList.add(i % 2 === 0 ? 'odd' : 'even');
-
- bodyElement.appendChild(rowElem);
- }
-
- this.paginator.update(this.totalRecords, this.perPage, this.currentPage);
- }
-
- _updatePage(n) {
- this.currentPage = n;
- this.paginator.update(this.totalRecords, this.perPage, this.currentPage);
- this._updateEntries({data: this.data});
- }
-
- _updateSort(field, direction) {
-
- }
-}
-
-const setupSite = function() {
- Array.prototype.forEach.call($$('.js-tag-input'), (el) => {
- new TagsInput(el).attach();
- });
-
- if (document.querySelector('#archive')) {
- const table = new DataTable(document.querySelector('#archive'), {
- ajaxCallback: (resolve) => {
- fetch('/api/ajax_pastes.php')
- .then(r => r.json())
- .then(resolve);
- },
- rowCallback: (rowData) => {
- const tags = rowData.tags.map((tagData) => {
- let tagColorClass;
- if (tagData.name.indexOf('nsfw') !== -1) {
- tagColorClass = 'is-danger';
- } else if (tagData.name.indexOf('safe') !== -1) {
- tagColorClass = 'is-success';
- } else if (tagData.name.indexOf('/') !== -1) {
- tagColorClass = 'is-primary';
- } else {
- tagColorClass = 'is-info';
- }
-
- return `
- ${escape(tagData.name)}
- `;
- }).join('');
-
- return `
- ${escape(rowData.title)} |
- ${escape(rowData.author)} |
- ${tags} |
-
`;
- }
- });
- table.attach();
- }
-
- const signupButton = $('[data-target~="#signin"],[data-target~="#signup"]');
-
- if (signupButton) {
- signupButton.addEventListener('click', () => {
- $('.modal').classList.add('is-active');
- });
-
- $('.modal-button-close').addEventListener('click', () => {
- $('.modal').classList.remove('is-active');
- });
- }
-
- const embedButton = $('.panel-tools .embed-tool');
-
- if (embedButton){
- embedButton.addEventListener('click', (evt) => {
- if (evt.target && evt.target.closest('.panel-tools')) {
- toggleEl(evt.target.closest('.panel-tools').querySelector('.panel-embed'));
- }
- });
- }
-
- const expandButton = $('.expand-tool');
-
- if (expandButton) {
- expandButton.addEventListener('click', (evt) => {
- if (evt.target && evt.target.closest('.panel')) {
- const panel = evt.target.closest('.panel');
-
- if (panel.classList.contains('panel-fullsize')) {
- panel.classList.remove('panel-fullsize');
- } else {
- panel.classList.add('panel-fullsize');
- }
- }
- });
- }
-};
-
-if (document.readyState !== 'loading') {
- setupSite();
-} else {
- document.addEventListener('DOMContentLoaded', setupSite);
-}
diff --git a/assets/bundle/bundle.min.js b/assets/bundle/bundle.min.js
deleted file mode 100644
index 85d1860..0000000
--- a/assets/bundle/bundle.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-function t(t,a){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!n){if(Array.isArray(t)||(n=function(t,a){if(!t)return;if("string"==typeof t)return e(t,a);var n=Object.prototype.toString.call(t).slice(8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return Array.from(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return e(t,a)}(t))||a&&t&&"number"==typeof t.length){n&&(t=n);var i=0,s=function(){};return{s:s,n:function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}},e:function(t){throw t},f:s}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,o=!0,l=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return o=t.done,t},e:function(t){l=!0,r=t},f:function(){try{o||null==n.return||n.return()}finally{if(l)throw r}}}}function e(t,e){(null==e||e>t.length)&&(e=t.length);for(var a=0,n=new Array(e);a/g,">").replace(/"/g,""").replace(/'/g,"'")},c=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};a(this,e),this.element=t,this.tags=[],this.options=n,this.maxTags=n.maxTags||10,this.inputNode=null,this.containerNode=null}return i(e,[{key:"attach",value:function(){if(this.element.style.display="none",this.containerNode=r(''),this.inputNode=r(''),this.containerNode.appendChild(this.inputNode),this.element.parentNode.insertBefore(this.containerNode,this.element.nextSibling),this.element.value){var e,a=t(this.element.value.split(","));try{for(a.s();!(e=a.n()).done;){var n=e.value;this.addTag(n)}}catch(t){a.e(t)}finally{a.f()}}this.containerNode.addEventListener("keydown",this._handleInputKeyUp.bind(this)),this.containerNode.addEventListener("click",this._handleContainerClick.bind(this))}},{key:"detach",value:function(){this.tags.clear(),this.containerNode.remove(),this.element.style.display="inline-block"}},{key:"updateHiddenInputValue",value:function(){this.element.value=this.tags.join(",")}},{key:"deleteTagNode",value:function(t){this.tags.splice(this.tags.indexOf(t.dataset.value.toLowerCase()),1),t.remove(),this.tags.length'+l(t)+''),this.inputNode),this.tags.length>=this.maxTags&&(this.inputNode.disabled=!0))}},{key:"_handleInputKeyUp",value:function(t){var e=this.inputNode.value;"Backspace"===t.key&&""===e?this.inputNode.previousSibling&&(this.deleteTagNode(this.inputNode.previousSibling),this.updateHiddenInputValue()):","===t.key&&(this.addTag(e),this.inputNode.value="",this.updateHiddenInputValue(),t.preventDefault())}},{key:"_handleContainerClick",value:function(t){t.target&&t.target.classList.contains("delete")&&(this.deleteTagNode(t.target.closest(".tag")),this.updateHiddenInputValue())}}]),e}(),d=function(){function t(e){a(this,t),this.element=e}return i(t,[{key:"attach",value:function(t){this.element.addEventListener("click",(function(e){e.target&&e.target.classList.contains("paginator__button")&&t(+e.target.dataset.page)}))}},{key:"update",value:function(t,e,a){o(this.element);var n=Math.floor(t/e),i=a-0<2?0:a-2<0?a:a-2,s=i+2>n?n:i+2+2,l=Math.abs(0-a)>2,c=Math.abs(n-a)>2,d=0===a?"disabled":"";this.element.appendChild(r('Previous'))),l&&(this.element.appendChild(r('').concat(0,""))),this.element.appendChild(r('…')));for(var u=i;u<=s;u++){var h=u===a?"paginator__button--selected":"";this.element.appendChild(r('').concat(u,"")))}c&&(this.element.appendChild(r('…')),this.element.appendChild(r('').concat(n,""))));var p=a===n?"disabled":"";this.element.appendChild(r('Next')))}}]),t}(),u=function(){function t(e,n){a(this,t),this.element=e,this.container=e.parentElement,this.options=n,this.ajaxCallback=n.ajaxCallback,this.data=[],this.totalRecords=-1,this.perPage=20,this.currentPage=0,this.paginator=new d(this.container.querySelector(".paginator"))}return i(t,[{key:"attach",value:function(){this.paginator.attach(this._updatePage.bind(this)),this._loadEntries()}},{key:"_loadEntries",value:function(){new Promise(this.ajaxCallback).then(this._updateEntries.bind(this))}},{key:"_updateEntries",value:function(t){this.data=t.data,this.totalRecords=this.data.length;var e=this.element.querySelector("tbody");o(e);for(var a=this.perPage*this.currentPage,n=a+this.perPage>this.totalRecords?this.totalRecords:a+this.perPage,i=a;i\n ').concat(l(t.name),"\n ")})).join("");return'\n ').concat(l(t.title),' | \n ').concat(l(t.author)," | \n ").concat(e," | \n
")}}).attach();var e=s('[data-target~="#signin"],[data-target~="#signup"]');e&&(e.addEventListener("click",(function(){s(".modal").classList.add("is-active")})),s(".modal-button-close").addEventListener("click",(function(){s(".modal").classList.remove("is-active")})));var a=s(".panel-tools .embed-tool");a&&a.addEventListener("click",(function(t){var e;t.target&&t.target.closest(".panel-tools")&&((e=t.target.closest(".panel-tools").querySelector(".panel-embed")).classList.contains("is-hidden")?e.classList.remove("is-hidden"):e.classList.add("is-hidden"))}));var n=s(".expand-tool");n&&n.addEventListener("click",(function(t){if(t.target&&t.target.closest(".panel")){var e=t.target.closest(".panel");e.classList.contains("panel-fullsize")?e.classList.remove("panel-fullsize"):e.classList.add("panel-fullsize")}}))};"loading"!==document.readyState?h():document.addEventListener("DOMContentLoaded",h);
-//# sourceMappingURL=bundle.min.js.map
diff --git a/assets/bundle/bundle.min.js.map b/assets/bundle/bundle.min.js.map
deleted file mode 100644
index 29cbc78..0000000
--- a/assets/bundle/bundle.min.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"bundle.min.js","sources":["../../js/dom.js","../../js/tag_input.js","../../js/data_tables.js","../../js/main.js"],"sourcesContent":["const $ = function(selector) {\n return document.querySelector(selector);\n};\n\nconst $$ = function(selector) {\n return document.querySelectorAll(selector) || [];\n};\n\nconst makeEl = function(html) {\n const template = document.createElement('template');\n\n template.innerHTML = html.trim();\n\n return template.content.firstChild;\n};\n\nconst clearEl = function(el) {\n while (el.firstChild) {\n el.removeChild(el.firstChild);\n }\n};\n\nconst toggleEl = function(el) {\n if (el.classList.contains('is-hidden')) {\n el.classList.remove('is-hidden');\n } else {\n el.classList.add('is-hidden');\n }\n};\n\nconst escape = function(unsafe) {\n return unsafe\n .replace(/&/g, \"&\")\n .replace(//g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n\nexport { $, $$, makeEl, clearEl, toggleEl, escape };","import { makeEl, escape } from \"./dom\";\n\nclass TagsInput {\n constructor(element, options = {}) {\n this.element = element;\n this.tags = [];\n this.options = options\n\n this.maxTags = options.maxTags || 10;\n this.inputNode = null;\n this.containerNode = null;\n }\n\n attach() {\n this.element.style.display = 'none';\n\n this.containerNode = makeEl('');\n this.inputNode = makeEl('');\n this.containerNode.appendChild(this.inputNode);\n\n this.element.parentNode.insertBefore(this.containerNode, this.element.nextSibling);\n\n /* Load existing tags from input */\n if (this.element.value) {\n for (const tag of this.element.value.split(',')) {\n this.addTag(tag);\n }\n }\n\n /* Handle addition and removal of tags via key-presses */\n this.containerNode.addEventListener('keydown', this._handleInputKeyUp.bind(this));\n\n /* Handle deletions by clicking the delete button */\n this.containerNode.addEventListener('click', this._handleContainerClick.bind(this));\n }\n\n detach() {\n this.tags.clear();\n this.containerNode.remove();\n this.element.style.display = 'inline-block';\n }\n\n updateHiddenInputValue() {\n this.element.value = this.tags.join(',');\n }\n\n deleteTagNode(node) {\n this.tags.splice(this.tags.indexOf(node.dataset.value.toLowerCase()), 1);\n node.remove();\n\n /* Below the limit? Make sure the input is enabled. */\n if (this.tags.length < this.maxTags) {\n this.inputNode.disabled = false;\n }\n }\n\n addTag(tagValue) {\n tagValue = tagValue.trim();\n\n /* Tag value is probably not empty and we don't already have the same tag. */\n if (tagValue !== '' && this.tags.indexOf(tagValue.toLowerCase()) === -1) {\n this.tags.push(tagValue.toLowerCase());\n\n this.inputNode.parentNode.insertBefore(\n makeEl('' + escape(tagValue) + ''),\n this.inputNode\n );\n\n /* Too many tags, disable the input for now. */\n if (this.tags.length >= this.maxTags) {\n this.inputNode.disabled = true;\n }\n }\n }\n\n _handleInputKeyUp(evt) {\n let tagValue = this.inputNode.value;\n\n if (evt.key === 'Backspace' && tagValue === '') {\n // Remove the child\n if (this.inputNode.previousSibling) {\n this.deleteTagNode(this.inputNode.previousSibling);\n\n this.updateHiddenInputValue();\n }\n } else if (evt.key === ',') {\n this.addTag(tagValue);\n\n this.inputNode.value = ''\n this.updateHiddenInputValue();\n\n evt.preventDefault();\n }\n }\n\n _handleContainerClick(evt) {\n if (evt.target && evt.target.classList.contains('delete')) {\n this.deleteTagNode(evt.target.closest('.tag'));\n this.updateHiddenInputValue();\n }\n }\n}\n\nexport { TagsInput };\n","import { makeEl, clearEl } from \"./dom\";\n\n\nclass SimplePaginator {\n constructor(element) {\n this.element = element;\n }\n\n attach(pageCallback) {\n this.element.addEventListener('click', evt => {\n if (evt.target && evt.target.classList.contains('paginator__button')) {\n pageCallback(+evt.target.dataset.page);\n }\n });\n }\n\n update(totalRecords, perPage, currentPage) {\n clearEl(this.element);\n\n /* First and last page in existence */\n const firstPage = 0;\n const lastPage = Math.floor(totalRecords / perPage); // ish?\n const numPagesToShow = 2;\n\n /* First and last page the main paginator will show */\n const firstPageShow = (currentPage - firstPage) < numPagesToShow ? firstPage : ((currentPage - numPagesToShow < 0) ? currentPage : currentPage - numPagesToShow);\n const lastPageShow = (firstPageShow + numPagesToShow) > lastPage ? lastPage : (firstPageShow + numPagesToShow + numPagesToShow);\n\n /* Whether to show the first and last pages in existence at the ends of the paginator */\n const showFirstPage = (Math.abs(firstPage - currentPage)) > (numPagesToShow);\n const showLastPage = (Math.abs(lastPage - currentPage)) > (numPagesToShow);\n\n\n const prevButtonDisabled = currentPage === firstPage ? 'disabled' : ''\n\n /* Previous button */\n this.element.appendChild(makeEl(\n `Previous`\n ));\n\n /* First page button */\n if (showFirstPage) {\n this.element.appendChild(makeEl(\n `${firstPage}`\n ));\n this.element.appendChild(makeEl(`…`));\n }\n\n /* \"window\" buttons */\n for (let i = firstPageShow; i <= lastPageShow; i++) {\n const selected = (i === currentPage ? 'paginator__button--selected' : '');\n this.element.appendChild(makeEl(\n `${i}`\n ));\n }\n\n /* Last page button */\n if (showLastPage) {\n this.element.appendChild(makeEl(`…`));\n this.element.appendChild(makeEl(\n `${lastPage}`\n ));\n }\n\n const nextButtonDisabled = currentPage === lastPage ? 'disabled' : ''\n /* Next button */\n this.element.appendChild(makeEl(\n `Next`\n ));\n }\n}\n\nclass DataTable {\n constructor(element, options) {\n this.element = element;\n this.container = element.parentElement;\n this.options = options;\n\n this.ajaxCallback = options.ajaxCallback;\n this.data = [];\n\n this.totalRecords = -1;\n this.perPage = 20;\n this.currentPage = 0;\n\n this.paginator = new SimplePaginator(this.container.querySelector('.paginator'));\n\n }\n\n attach() {\n this.paginator.attach(this._updatePage.bind(this));\n this._loadEntries();\n }\n\n /* Load the requested data from the server, and when done, update the DOM. */\n _loadEntries() {\n new Promise(this.ajaxCallback)\n .then(this._updateEntries.bind(this));\n }\n\n /* Update the DOM to reflect the current state of the data we have loaded */\n _updateEntries(data) {\n this.data = data.data;\n this.totalRecords = this.data.length;\n\n const bodyElement = this.element.querySelector('tbody');\n clearEl(bodyElement);\n\n const firstIndex = (this.perPage * this.currentPage);\n const lastIndex = (firstIndex + this.perPage) > this.totalRecords ? this.totalRecords : (firstIndex + this.perPage);\n\n\n for (let i = firstIndex; i < lastIndex; i++) {\n const rowElem = makeEl(this.options.rowCallback(this.data[i]));\n rowElem.classList.add(i % 2 === 0 ? 'odd' : 'even');\n\n bodyElement.appendChild(rowElem);\n }\n\n this.paginator.update(this.totalRecords, this.perPage, this.currentPage);\n }\n\n _updatePage(n) {\n this.currentPage = n;\n this.paginator.update(this.totalRecords, this.perPage, this.currentPage);\n this._updateEntries({data: this.data});\n }\n\n _updateSort(field, direction) {\n\n }\n}\n\nexport { DataTable };\n","import { $, $$, escape, toggleEl } from './dom';\nimport { TagsInput } from \"./tag_input\";\nimport { DataTable } from \"./data_tables\";\n\nconst setupSite = function() {\n Array.prototype.forEach.call($$('.js-tag-input'), (el) => {\n new TagsInput(el).attach();\n });\n\n if (document.querySelector('#archive')) {\n const table = new DataTable(document.querySelector('#archive'), {\n ajaxCallback: (resolve) => {\n fetch('/api/ajax_pastes.php')\n .then(r => r.json())\n .then(resolve);\n },\n rowCallback: (rowData) => {\n const tags = rowData.tags.map((tagData) => {\n let tagColorClass;\n if (tagData.name.indexOf('nsfw') !== -1) {\n tagColorClass = 'is-danger';\n } else if (tagData.name.indexOf('safe') !== -1) {\n tagColorClass = 'is-success';\n } else if (tagData.name.indexOf('/') !== -1) {\n tagColorClass = 'is-primary';\n } else {\n tagColorClass = 'is-info';\n }\n\n return `\n ${escape(tagData.name)}\n `;\n }).join('');\n\n return `\n ${escape(rowData.title)} | \n ${escape(rowData.author)} | \n ${tags} | \n
`;\n }\n });\n table.attach();\n }\n\n const signupButton = $('[data-target~=\"#signin\"],[data-target~=\"#signup\"]');\n\n if (signupButton) {\n signupButton.addEventListener('click', () => {\n $('.modal').classList.add('is-active');\n });\n\n $('.modal-button-close').addEventListener('click', () => {\n $('.modal').classList.remove('is-active');\n });\n }\n\n const embedButton = $('.panel-tools .embed-tool');\n\n if (embedButton){\n embedButton.addEventListener('click', (evt) => {\n if (evt.target && evt.target.closest('.panel-tools')) {\n toggleEl(evt.target.closest('.panel-tools').querySelector('.panel-embed'));\n }\n });\n }\n\n const expandButton = $('.expand-tool');\n\n if (expandButton) {\n expandButton.addEventListener('click', (evt) => {\n if (evt.target && evt.target.closest('.panel')) {\n const panel = evt.target.closest('.panel');\n\n if (panel.classList.contains('panel-fullsize')) {\n panel.classList.remove('panel-fullsize');\n } else {\n panel.classList.add('panel-fullsize');\n }\n }\n });\n }\n};\n\nif (document.readyState !== 'loading') {\n setupSite();\n} else {\n document.addEventListener('DOMContentLoaded', setupSite);\n}\n"],"names":["$","selector","document","querySelector","makeEl","html","template","createElement","innerHTML","trim","content","firstChild","clearEl","el","removeChild","escape","unsafe","replace","TagsInput","element","options","tags","maxTags","inputNode","containerNode","style","display","appendChild","this","parentNode","insertBefore","nextSibling","value","split","tag","addTag","addEventListener","_handleInputKeyUp","bind","_handleContainerClick","clear","remove","join","node","splice","indexOf","dataset","toLowerCase","length","disabled","tagValue","push","evt","key","previousSibling","deleteTagNode","updateHiddenInputValue","preventDefault","target","classList","contains","closest","SimplePaginator","pageCallback","page","totalRecords","perPage","currentPage","lastPage","Math","floor","firstPageShow","lastPageShow","showFirstPage","abs","showLastPage","prevButtonDisabled","i","selected","nextButtonDisabled","DataTable","container","parentElement","ajaxCallback","data","paginator","attach","_updatePage","_loadEntries","Promise","then","_updateEntries","bodyElement","firstIndex","lastIndex","rowElem","rowCallback","add","update","n","field","direction","setupSite","Array","prototype","forEach","call","querySelectorAll","resolve","fetch","r","json","rowData","map","tagData","tagColorClass","name","slug","id","title","author","signupButton","embedButton","expandButton","panel","readyState"],"mappings":"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"}
\ No newline at end of file
diff --git a/includes/common.php b/includes/common.php
index 3933acb..87db6c3 100644
--- a/includes/common.php
+++ b/includes/common.php
@@ -15,6 +15,14 @@ use PonePaste\Models\Paste;
use PonePaste\Models\User;
/* View functions */
+function javascriptIncludeTag(string $name) : string {
+ if (PP_DEBUG) {
+ return "";
+ }
+
+ return "";
+}
+
function urlForPage($page = '') : string {
if (!PP_MOD_REWRITE) {
$page .= '.php';
@@ -204,6 +212,8 @@ $total_unique_views = PageView::select('tvisit')->orderBy('id', 'desc')->first()
$current_user = SessionHelper::currentUser();
+$script_bundles = [];
+
/* Security headers */
header('X-Frame-Options: SAMEORIGIN');
header('X-Content-Type-Options: nosniff');
diff --git a/index.php b/index.php
index beb88dd..ced4c5c 100644
--- a/index.php
+++ b/index.php
@@ -126,7 +126,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($editing) {
$paste = Paste::find($_POST['paste_id']);
if ($current_user &&
- $current_user->user_id === $paste->user_id) {
+ $current_user->id === $paste->user_id) {
$paste_id = $paste->id;
$paste->update([
'title' => $paste_title,
diff --git a/js/archive.js b/js/archive.js
index 9d317cf..3241ce8 100644
--- a/js/archive.js
+++ b/js/archive.js
@@ -1,3 +1,44 @@
-import { $ } from './dom';
+import { escape, whenReady } from './dom';
import { DataTable } from './data_tables';
+import { globalSetup } from './main';
+whenReady(() => {
+ globalSetup();
+
+ const urlParams = new URLSearchParams(window.location.search);
+ const myParam = urlParams.get('q');
+ const apiUrl = myParam !== null ? '/api/ajax_pastes.php?q=' + myParam : '/api/ajax_pastes.php';
+
+ const table = new DataTable(document.getElementById('archive'), {
+ ajaxCallback: (resolve) => {
+ fetch(apiUrl)
+ .then(r => r.json())
+ .then(resolve);
+ },
+ rowCallback: (rowData) => {
+ const tags = rowData.tags.map((tagData) => {
+ let tagColorClass;
+ if (tagData.name.indexOf('nsfw') !== -1) {
+ tagColorClass = 'is-danger';
+ } else if (tagData.name.indexOf('safe') !== -1) {
+ tagColorClass = 'is-success';
+ } else if (tagData.name.indexOf('/') !== -1) {
+ tagColorClass = 'is-primary';
+ } else {
+ tagColorClass = 'is-info';
+ }
+
+ return `
+ ${escape(tagData.name)}
+ `;
+ }).join('');
+
+ return `
+ ${escape(rowData.title)} |
+ ${escape(rowData.author)} |
+ ${tags} |
+
`;
+ }
+ });
+ table.attach();
+});
\ No newline at end of file
diff --git a/js/dom.js b/js/dom.js
index 6212b6e..3e8cbe1 100644
--- a/js/dom.js
+++ b/js/dom.js
@@ -37,5 +37,12 @@ const escape = function(unsafe) {
.replace(/'/g, "'");
}
+const whenReady = function(funcp) {
+ if (document.readyState !== 'loading') {
+ funcp();
+ } else {
+ document.addEventListener('DOMContentLoaded', funcp);
+ }
+}
-export { $, $$, makeEl, clearEl, toggleEl, escape };
\ No newline at end of file
+export { whenReady, $, $$, makeEl, clearEl, toggleEl, escape };
\ No newline at end of file
diff --git a/js/generic.js b/js/generic.js
new file mode 100644
index 0000000..a9cc177
--- /dev/null
+++ b/js/generic.js
@@ -0,0 +1,4 @@
+import { whenReady } from "./dom";
+import { globalSetup } from "./main";
+
+whenReady(globalSetup);
diff --git a/js/main.js b/js/main.js
index 1aaf269..826f55a 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1,47 +1,7 @@
-import { $, $$, escape, toggleEl } from './dom';
+import { $, $$, toggleEl } from './dom';
import { TagsInput } from "./tag_input";
-import { DataTable } from "./data_tables";
-
-const setupSite = function() {
- Array.prototype.forEach.call($$('.js-tag-input'), (el) => {
- new TagsInput(el).attach();
- });
-
- if (document.querySelector('#archive')) {
- const table = new DataTable(document.querySelector('#archive'), {
- ajaxCallback: (resolve) => {
- fetch('/api/ajax_pastes.php')
- .then(r => r.json())
- .then(resolve);
- },
- rowCallback: (rowData) => {
- const tags = rowData.tags.map((tagData) => {
- let tagColorClass;
- if (tagData.name.indexOf('nsfw') !== -1) {
- tagColorClass = 'is-danger';
- } else if (tagData.name.indexOf('safe') !== -1) {
- tagColorClass = 'is-success';
- } else if (tagData.name.indexOf('/') !== -1) {
- tagColorClass = 'is-primary';
- } else {
- tagColorClass = 'is-info';
- }
-
- return `
- ${escape(tagData.name)}
- `;
- }).join('');
-
- return `
- ${escape(rowData.title)} |
- ${escape(rowData.author)} |
- ${tags} |
-
`;
- }
- });
- table.attach();
- }
+const setupSignupModal = () => {
const signupButton = $('[data-target~="#signin"],[data-target~="#signup"]');
if (signupButton) {
@@ -53,6 +13,14 @@ const setupSite = function() {
$('.modal').classList.remove('is-active');
});
}
+}
+
+const globalSetup = () => {
+ Array.prototype.forEach.call($$('.js-tag-input'), (el) => {
+ new TagsInput(el).attach();
+ });
+
+ setupSignupModal();
const embedButton = $('.panel-tools .embed-tool');
@@ -79,10 +47,36 @@ const setupSite = function() {
}
});
}
-};
-if (document.readyState !== 'loading') {
- setupSite();
-} else {
- document.addEventListener('DOMContentLoaded', setupSite);
+ // Notifications
+ (document.querySelectorAll('.notification .delete') || []).forEach(($delete) => {
+ const $notification = $delete.parentNode;
+
+ $delete.addEventListener('click', () => {
+ $notification.parentNode.removeChild($notification);
+ });
+ });
+
+ // Hamburger menu
+ const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
+ if ($navbarBurgers.length > 0) {
+ $navbarBurgers.forEach(el => {
+ el.addEventListener('click', () => {
+ const target = el.dataset.target;
+ const $target = document.getElementById(target);
+ el.classList.toggle('is-active');
+ $target.classList.toggle('is-active');
+ });
+ });
+ }
+
+ const preloader = $('.preloader');
+ const main = $('main');
+
+ if (preloader && main) {
+ preloader.remove();
+ main.id = '';
+ }
}
+
+export { globalSetup };
\ No newline at end of file
diff --git a/paste.php b/paste.php
index 81414bf..e3f30c9 100644
--- a/paste.php
+++ b/paste.php
@@ -8,6 +8,10 @@ use Highlight\Highlighter;
use PonePaste\Models\Paste;
use PonePaste\Models\User;
+function isRequesterLikelyBot() : bool {
+ return str_contains(strtolower($_SERVER['HTTP_USER_AGENT']), 'bot');
+}
+
function rawView($content, $p_code) {
if ($p_code) {
header('Content-Type: text/plain');
@@ -147,7 +151,7 @@ if (isset($_GET['raw'])) {
// Deletion
if (isset($_POST['delete'])) {
- if (!$current_user || ($paste_owner_id !== $current_user->user_id)) {
+ if (!$current_user || ($paste_owner_id !== $current_user->id)) {
flashError('You must be logged in and own this paste to delete it.');
} else {
$paste->delete();
@@ -210,7 +214,7 @@ if ($password_required && $password_valid) {
}
// View counter
-if (@$_SESSION['not_unique'] !== $paste_id) {
+if (!isRequesterLikelyBot() && @$_SESSION['not_unique'] !== $paste_id) {
$_SESSION['not_unique'] = $paste_id;
$paste->views += 1;
$paste->save();
diff --git a/rollup.config.js b/rollup.config.js
index ba2ed03..91f3ed9 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -1,20 +1,27 @@
-// noinspection JSUnusedGlobalSymbols
+// noinspection JSUnusedGlobalSymbols,JSCheckFunctionSignatures
-import { getBabelOutputPlugin } from '@rollup/plugin-babel';
-import { terser } from 'rollup-plugin-terser';
+import {getBabelOutputPlugin} from '@rollup/plugin-babel';
+import {terser} from 'rollup-plugin-terser';
-export default {
- input: 'js/main.js',
- output: [
- {
- file: 'assets/bundle/bundle.js',
- format: 'esm'
- },
- {
- file: 'assets/bundle/bundle.min.js',
- format: 'esm',
- plugins: [getBabelOutputPlugin({ presets: ['@babel/preset-env'] }), terser()],
- sourcemap: true
- }
- ]
+const output = (name) => {
+ return {
+ input: `js/${name}.js`,
+ output: [
+ {
+ file: `assets/bundle/${name}.js`,
+ format: 'esm'
+ },
+ {
+ file: `assets/bundle/${name}.min.js`,
+ format: 'esm',
+ plugins: [getBabelOutputPlugin({ presets: ['@babel/preset-env'] }), terser()],
+ sourcemap: true
+ }
+ ]
+ }
};
+
+export default [
+ output('generic'),
+ output('archive')
+];
\ No newline at end of file
diff --git a/theme/bulma/archive.php b/theme/bulma/archive.php
index fc3e992..0fc2b53 100644
--- a/theme/bulma/archive.php
+++ b/theme/bulma/archive.php
@@ -4,7 +4,7 @@
rowReorder: {selector: 'td:nth-child(2)'},
responsive: true,
processing: true,
- language: {processing: 'Loading... '},
+ language: {processing: ''},
autoWidth: false,
ajax: "api/ajax_pastes.php",
initComplete: function () {
@@ -57,6 +57,7 @@
+
diff --git a/theme/bulma/common.php b/theme/bulma/common.php
index 66d988b..2dd29ce 100644
--- a/theme/bulma/common.php
+++ b/theme/bulma/common.php
@@ -32,9 +32,6 @@ $flashes = getFlashes();
-
-
-
@@ -288,16 +285,15 @@ $flashes = getFlashes();
-
+
+
+ = javascriptIncludeTag('generic') ?>
+
+
+ = javascriptIncludeTag($bundle) ?>
+
+
-
-
-