diff --git a/infra/database.js b/infra/database.js
index fd55d03b4..81f350d02 100644
--- a/infra/database.js
+++ b/infra/database.js
@@ -11,7 +11,7 @@ const configurations = {
database: process.env.POSTGRES_DB,
password: process.env.POSTGRES_PASSWORD,
port: process.env.POSTGRES_PORT,
- connectionTimeoutMillis: 1000,
+ connectionTimeoutMillis: 2000,
idleTimeoutMillis: 30000,
max: 1,
ssl: {
diff --git a/jsconfig.json b/jsconfig.json
index 36aa1a4dc..3ba6eb299 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -1,5 +1,8 @@
{
"compilerOptions": {
- "baseUrl": "."
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["pages/interface/components/*"]
+ }
}
}
diff --git a/models/rss.js b/models/rss.js
index 51cb6c148..cf12d8027 100644
--- a/models/rss.js
+++ b/models/rss.js
@@ -1,6 +1,6 @@
-import { renderToStaticMarkup } from 'react-dom/server';
-import { Viewer } from 'pages/interface';
+import { Viewer } from '@/TabNewsUI';
import removeMarkdown from 'models/remove-markdown';
+import { renderToStaticMarkup } from 'react-dom/server';
import { Feed } from 'feed';
import webserver from 'infra/webserver.js';
diff --git a/package-lock.json b/package-lock.json
index f162d884d..364222ac3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -28,9 +28,6 @@
"cross-fetch": "3.1.5",
"date-fns": "2.29.3",
"feed": "4.2.2",
- "github-markdown-css": "5.2.0",
- "highlight.js": "11.7.0",
- "ip-anonymize": "0.1.0",
"is-in-subnet": "4.0.1",
"joi": "17.8.3",
"next": "13.2.4",
@@ -3125,7 +3122,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
+ "devOptional": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -3500,6 +3497,16 @@
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
},
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "optional": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@@ -3525,7 +3532,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
+ "devOptional": true,
"dependencies": {
"fill-range": "^7.0.1"
},
@@ -3781,6 +3788,47 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/ci-info": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
@@ -6236,7 +6284,7 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
+ "devOptional": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -6369,7 +6417,6 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -6528,14 +6575,6 @@
"node": ">=10"
}
},
- "node_modules/github-markdown-css": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.2.0.tgz",
- "integrity": "sha512-hq5RaCInSUZ48bImOZpkppW2/MT44StRgsbsZ8YA4vJFwLKB/Vo3k7R2t+pUGqO+ThG0QDMi96TewV/B3vyItg==",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -7109,6 +7148,13 @@
"node": ">= 4"
}
},
+ "node_modules/immutable": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
+ "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==",
+ "optional": true,
+ "peer": true
+ },
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -7241,11 +7287,6 @@
"node": ">=12"
}
},
- "node_modules/ip-anonymize": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/ip-anonymize/-/ip-anonymize-0.1.0.tgz",
- "integrity": "sha512-cZJu+N5JKKFGMK0eEQWNaQMn2EhCysciVM6eotCJwfqotj16BTfVchKsJCH6mQAT9N0GC7oWRcsZ6Lb8dDiwTA=="
- },
"node_modules/is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
@@ -7294,6 +7335,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-boolean-object": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
@@ -7390,7 +7444,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
+ "devOptional": true,
"engines": {
"node": ">=0.10.0"
}
@@ -7420,7 +7474,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
+ "devOptional": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
@@ -7470,7 +7524,7 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
+ "devOptional": true,
"engines": {
"node": ">=0.12.0"
}
@@ -10330,7 +10384,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
+ "devOptional": true,
"engines": {
"node": ">=0.10.0"
}
@@ -11495,6 +11549,19 @@
"node": ">= 6"
}
},
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
"node_modules/real-require": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
@@ -12022,6 +12089,24 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
+ "node_modules/sass": {
+ "version": "1.60.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.60.0.tgz",
+ "integrity": "sha512-updbwW6fNb5gGm8qMXzVO7V4sWf7LMXnMly/JEyfbfERbVH46Fn6q02BX7/eHTdKpE7d+oTkMMQpFWNUMfFbgQ==",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "chokidar": ">=3.0.0 <4.0.0",
+ "immutable": "^4.0.0",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
@@ -12763,7 +12848,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
+ "devOptional": true,
"dependencies": {
"is-number": "^7.0.0"
},
@@ -15885,7 +15970,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
+ "devOptional": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -16154,6 +16239,13 @@
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
},
+ "binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "optional": true,
+ "peer": true
+ },
"bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@@ -16179,7 +16271,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
+ "devOptional": true,
"requires": {
"fill-range": "^7.0.1"
}
@@ -16343,6 +16435,35 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
+ "chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "optional": true,
+ "peer": true,
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "optional": true,
+ "peer": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
"ci-info": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
@@ -18191,7 +18312,7 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
+ "devOptional": true,
"requires": {
"to-regex-range": "^5.0.1"
}
@@ -18296,7 +18417,6 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
"optional": true
},
"function-bind": {
@@ -18402,11 +18522,6 @@
"through2": "^4.0.0"
}
},
- "github-markdown-css": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.2.0.tgz",
- "integrity": "sha512-hq5RaCInSUZ48bImOZpkppW2/MT44StRgsbsZ8YA4vJFwLKB/Vo3k7R2t+pUGqO+ThG0QDMi96TewV/B3vyItg=="
- },
"glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -18823,6 +18938,13 @@
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
"dev": true
},
+ "immutable": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
+ "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==",
+ "optional": true,
+ "peer": true
+ },
"import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -18924,11 +19046,6 @@
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="
},
- "ip-anonymize": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/ip-anonymize/-/ip-anonymize-0.1.0.tgz",
- "integrity": "sha512-cZJu+N5JKKFGMK0eEQWNaQMn2EhCysciVM6eotCJwfqotj16BTfVchKsJCH6mQAT9N0GC7oWRcsZ6Lb8dDiwTA=="
- },
"is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
@@ -18965,6 +19082,16 @@
"has-bigints": "^1.0.1"
}
},
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "optional": true,
+ "peer": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
"is-boolean-object": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
@@ -19014,7 +19141,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true
+ "devOptional": true
},
"is-fullwidth-code-point": {
"version": "4.0.0",
@@ -19032,7 +19159,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
+ "devOptional": true,
"requires": {
"is-extglob": "^2.1.1"
}
@@ -19064,7 +19191,7 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true
+ "devOptional": true
},
"is-number-object": {
"version": "1.0.7",
@@ -21068,7 +21195,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true
+ "devOptional": true
},
"normalize-range": {
"version": "0.1.2",
@@ -21891,6 +22018,16 @@
"util-deprecate": "^1.0.1"
}
},
+ "readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "optional": true,
+ "peer": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
"real-require": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
@@ -22264,6 +22401,18 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
+ "sass": {
+ "version": "1.60.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.60.0.tgz",
+ "integrity": "sha512-updbwW6fNb5gGm8qMXzVO7V4sWf7LMXnMly/JEyfbfERbVH46Fn6q02BX7/eHTdKpE7d+oTkMMQpFWNUMfFbgQ==",
+ "optional": true,
+ "peer": true,
+ "requires": {
+ "chokidar": ">=3.0.0 <4.0.0",
+ "immutable": "^4.0.0",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ }
+ },
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
@@ -22842,7 +22991,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
+ "devOptional": true,
"requires": {
"is-number": "^7.0.0"
}
diff --git a/package.json b/package.json
index 5a9583faf..9d53d9c83 100644
--- a/package.json
+++ b/package.json
@@ -19,9 +19,6 @@
"cross-fetch": "3.1.5",
"date-fns": "2.29.3",
"feed": "4.2.2",
- "github-markdown-css": "5.2.0",
- "highlight.js": "11.7.0",
- "ip-anonymize": "0.1.0",
"is-in-subnet": "4.0.1",
"joi": "17.8.3",
"next": "13.2.4",
diff --git a/pages/404.public.js b/pages/404.public.js
index d8e99729c..49632b2f3 100644
--- a/pages/404.public.js
+++ b/pages/404.public.js
@@ -1,6 +1,5 @@
+import { Box, DefaultLayout, Link } from '@/TabNewsUI';
import Image from 'next/image';
-import { DefaultLayout } from 'pages/interface/index.js';
-import { Box, Link } from '@primer/react';
import botSleepyFaceDarkTransparent from 'public/brand/bot-sleepy-face-dark-transparent.svg';
export default function Custom404() {
diff --git a/pages/500.public.js b/pages/500.public.js
index 241759ed4..92ace58f1 100644
--- a/pages/500.public.js
+++ b/pages/500.public.js
@@ -1,6 +1,5 @@
+import { Box, DefaultLayout, Link } from '@/TabNewsUI';
import Image from 'next/image';
-import { DefaultLayout } from 'pages/interface/index.js';
-import { Box, Link } from '@primer/react';
import botDeadFaceDarkTransparent from 'public/brand/bot-dead-face-dark-transparent.svg';
export default function Custom500() {
diff --git a/pages/[username]/[slug]/index.public.js b/pages/[username]/[slug]/index.public.js
index 145922584..91b449063 100644
--- a/pages/[username]/[slug]/index.public.js
+++ b/pages/[username]/[slug]/index.public.js
@@ -1,15 +1,15 @@
-import useSWR from 'swr';
-import { useEffect, useState } from 'react';
-import { Link, DefaultLayout, Content, TabCoinButtons, Confetti, useCollapse } from 'pages/interface/index.js';
-import user from 'models/user.js';
-import content from 'models/content.js';
-import validator from 'models/validator.js';
-import authorization from 'models/authorization.js';
-import removeMarkdown from 'models/remove-markdown.js';
+import { Box, Button, Confetti, Content, DefaultLayout, Link, TabCoinButtons, Tooltip } from '@/TabNewsUI';
+import { CommentDiscussionIcon, CommentIcon, FoldIcon, UnfoldIcon } from '@primer/octicons-react';
import { NotFoundError } from 'errors/index.js';
-import { Box, Button, Tooltip } from '@primer/react';
-import { CommentIcon, CommentDiscussionIcon, FoldIcon, UnfoldIcon } from '@primer/octicons-react';
import webserver from 'infra/webserver.js';
+import authorization from 'models/authorization.js';
+import content from 'models/content.js';
+import removeMarkdown from 'models/remove-markdown.js';
+import user from 'models/user.js';
+import validator from 'models/validator.js';
+import { useCollapse } from 'pages/interface';
+import { useEffect, useState } from 'react';
+import useSWR from 'swr';
export default function Post({
contentFound: contentFoundFallback,
@@ -74,7 +74,7 @@ export default function Post({
sx={{
borderWidth: 0,
borderRightWidth: 1,
- borderColor: 'border.muted',
+ borderColor: 'btn.activeBorder',
borderStyle: 'dotted',
width: '50%',
height: '100%',
@@ -82,7 +82,7 @@ export default function Post({
/>
-
+
@@ -246,7 +246,7 @@ function RenderChildrenTree({ childrenList, renderIntent, renderIncrement }) {
borderStyle: 'dashed',
},
svg: {
- backgroundColor: 'white',
+ backgroundColor: 'canvas.default',
},
},
}}>
@@ -266,7 +266,7 @@ function RenderChildrenTree({ childrenList, renderIntent, renderIncrement }) {
borderWidth: 0,
borderRightWidth: 1,
borderLeftWidth: 0,
- borderColor: 'border.muted',
+ borderColor: 'btn.activeBorder',
borderStyle: 'dotted',
width: 0,
transition: 'border 0.1s cubic-bezier(1,1,1,0)',
@@ -275,7 +275,7 @@ function RenderChildrenTree({ childrenList, renderIntent, renderIncrement }) {
-
+
diff --git a/pages/[username]/index.public.js b/pages/[username]/index.public.js
index 0ac16739f..e3e486b06 100644
--- a/pages/[username]/index.public.js
+++ b/pages/[username]/index.public.js
@@ -1,16 +1,28 @@
-import useSWR from 'swr';
-import { useState } from 'react';
-import { DefaultLayout, ContentList, useUser } from 'pages/interface/index.js';
-import user from 'models/user.js';
-import content from 'models/content.js';
+import {
+ ActionList,
+ ActionMenu,
+ Box,
+ ContentList,
+ DefaultLayout,
+ Flash,
+ IconButton,
+ Label,
+ LabelGroup,
+ Pagehead,
+ useConfirm,
+} from '@/TabNewsUI';
+import { KebabHorizontalIcon, TrashIcon } from '@primer/octicons-react';
+import { NotFoundError } from 'errors/index.js';
import authorization from 'models/authorization.js';
-import validator from 'models/validator.js';
+import content from 'models/content.js';
import removeMarkdown from 'models/remove-markdown.js';
-import { NotFoundError } from 'errors/index.js';
-import { FaUser } from 'react-icons/fa';
+import user from 'models/user.js';
+import validator from 'models/validator.js';
import { useRouter } from 'next/router';
-import { Box, Pagehead, ActionMenu, ActionList, Flash, IconButton, useConfirm, LabelGroup, Label } from '@primer/react';
-import { KebabHorizontalIcon, TrashIcon } from '@primer/octicons-react';
+import { useUser } from 'pages/interface';
+import { useState } from 'react';
+import { FaUser } from 'react-icons/fa';
+import useSWR from 'swr';
export default function Home({ contentListFound, pagination, userFound: userFoundFallback }) {
const { data: userFound, mutate: userFoundMutate } = useSWR(`/api/v1/users/${userFoundFallback.username}`, {
diff --git a/pages/[username]/pagina/[page]/index.public.js b/pages/[username]/pagina/[page]/index.public.js
index 9788ede1a..d478cb8c3 100644
--- a/pages/[username]/pagina/[page]/index.public.js
+++ b/pages/[username]/pagina/[page]/index.public.js
@@ -1,4 +1,4 @@
-import { DefaultLayout, ContentList } from 'pages/interface/index.js';
+import { DefaultLayout, ContentList } from '@/TabNewsUI';
import user from 'models/user.js';
import content from 'models/content.js';
import authorization from 'models/authorization.js';
diff --git a/pages/_app.public.js b/pages/_app.public.js
index ec9ff3571..6478d1c79 100644
--- a/pages/_app.public.js
+++ b/pages/_app.public.js
@@ -1,9 +1,7 @@
-import { ThemeProvider, BaseStyles, SSRProvider } from '@primer/react';
+import { ThemeProvider } from '@/TabNewsUI';
import { Analytics } from '@vercel/analytics/react';
+import { DefaultHead, UserProvider } from 'pages/interface';
import { SWRConfig } from 'swr';
-import { UserProvider } from 'pages/interface/hooks/useUser/index.js';
-import NextNProgress from 'pages/interface/components/Progressbar/index.js';
-import { DefaultHead } from 'pages/interface/components/Head/index.js';
async function SWRFetcher(resource, init) {
const response = await fetch(resource, init);
@@ -14,25 +12,15 @@ async function SWRFetcher(resource, init) {
function MyApp({ Component, pageProps }) {
return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
- >
+
);
}
diff --git a/pages/_document.public.js b/pages/_document.public.js
index 222e690bf..01c85dc54 100644
--- a/pages/_document.public.js
+++ b/pages/_document.public.js
@@ -1,6 +1,9 @@
-import Document, { Html, Head, Main, NextScript } from 'next/document';
+import Document, { Head, Html, Main, NextScript } from 'next/document';
+import Script from 'next/script';
import { ServerStyleSheet } from 'styled-components';
+const noFlashScript = `document.documentElement.setAttribute('data-no-flash', true)`;
+
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
@@ -32,6 +35,9 @@ export default class MyDocument extends Document {
+
diff --git a/pages/cadastro/ativar/[token].public.js b/pages/cadastro/ativar/[token].public.js
index 7fc83672e..00aea7099 100644
--- a/pages/cadastro/ativar/[token].public.js
+++ b/pages/cadastro/ativar/[token].public.js
@@ -1,8 +1,7 @@
+import { Box, Confetti, DefaultLayout, Flash } from '@/TabNewsUI';
import fetch from 'cross-fetch';
-import { Box, Flash } from '@primer/react';
-import { DefaultLayout, Confetti } from 'pages/interface/index.js';
-import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
export default function ActiveUser() {
const router = useRouter();
diff --git a/pages/cadastro/confirmar/index.public.js b/pages/cadastro/confirmar/index.public.js
index 6d0a3d608..2e236d269 100644
--- a/pages/cadastro/confirmar/index.public.js
+++ b/pages/cadastro/confirmar/index.public.js
@@ -1,6 +1,5 @@
-import { Box, Heading, Text } from '@primer/react';
-import { useState, useEffect } from 'react';
-import { DefaultLayout } from 'pages/interface/index.js';
+import { Box, DefaultLayout, Heading, Text } from '@/TabNewsUI';
+import { useEffect, useState } from 'react';
export default function ConfirmSignup() {
const [email, setEmail] = useState('');
diff --git a/pages/cadastro/index.public.js b/pages/cadastro/index.public.js
index ecc94faf3..b95c0b232 100644
--- a/pages/cadastro/index.public.js
+++ b/pages/cadastro/index.public.js
@@ -1,7 +1,6 @@
-import { useState, useRef } from 'react';
+import { Box, Button, DefaultLayout, Flash, FormControl, Heading, PasswordInput, TextInput } from '@/TabNewsUI';
import { useRouter } from 'next/router';
-import { DefaultLayout, PasswordInput } from 'pages/interface/index.js';
-import { FormControl, Box, Heading, Button, TextInput, Flash } from '@primer/react';
+import { useRef, useState } from 'react';
export default function Register() {
return (
@@ -111,7 +110,8 @@ function SignUpForm() {
spellCheck={false}
block={true}
aria-label="Seu nome de usuário"
- sx={{ minHeight: '46px' }}
+ contrast
+ sx={{ minHeight: '46px', px: 2, '&:focus-within': { backgroundColor: 'canvas.default' } }}
/>
{errorObject?.key === 'username' && (
{errorObject.message}
@@ -133,7 +133,8 @@ function SignUpForm() {
spellCheck={false}
block={true}
aria-label="Seu email"
- sx={{ minHeight: '46px' }}
+ contrast
+ sx={{ minHeight: '46px', px: 2, '&:focus-within': { backgroundColor: 'canvas.default' } }}
/>
{errorObject?.key === 'email' && (
{errorObject.message}
diff --git a/pages/cadastro/recuperar/[token].public.js b/pages/cadastro/recuperar/[token].public.js
index ff3a6e5c4..1c6e072bd 100644
--- a/pages/cadastro/recuperar/[token].public.js
+++ b/pages/cadastro/recuperar/[token].public.js
@@ -1,8 +1,7 @@
-import { useState, useRef } from 'react';
+import { Box, Button, DefaultLayout, Flash, FormControl, Heading, PasswordInput } from '@/TabNewsUI';
import fetch from 'cross-fetch';
-import { FormControl, Box, Heading, Button, Flash } from '@primer/react';
-import { DefaultLayout, PasswordInput } from 'pages/interface/index.js';
import { useRouter } from 'next/router';
+import { useRef, useState } from 'react';
export default function RecoverPassword() {
return (
diff --git a/pages/cadastro/recuperar/confirmar/index.public.js b/pages/cadastro/recuperar/confirmar/index.public.js
index 9452e7194..980f0c124 100644
--- a/pages/cadastro/recuperar/confirmar/index.public.js
+++ b/pages/cadastro/recuperar/confirmar/index.public.js
@@ -1,5 +1,4 @@
-import { Box, Heading, Text } from '@primer/react';
-import { DefaultLayout } from 'pages/interface/index.js';
+import { Box, DefaultLayout, Heading, Text } from '@/TabNewsUI';
export default function ConfirmRecoverPassword() {
return (
diff --git a/pages/cadastro/recuperar/index.public.js b/pages/cadastro/recuperar/index.public.js
index 074105c28..4b442d9d6 100644
--- a/pages/cadastro/recuperar/index.public.js
+++ b/pages/cadastro/recuperar/index.public.js
@@ -1,7 +1,7 @@
-import { useState, useRef, useEffect } from 'react';
+import { Box, Button, DefaultLayout, Flash, FormControl, Heading, TextInput } from '@/TabNewsUI';
import { useRouter } from 'next/router';
-import { DefaultLayout, useUser } from 'pages/interface/index.js';
-import { FormControl, Box, Heading, Button, TextInput, Flash } from '@primer/react';
+import { useUser } from 'pages/interface';
+import { useEffect, useRef, useState } from 'react';
export default function RecoverPassword() {
return (
@@ -110,6 +110,8 @@ function RecoverPasswordForm() {
Digite seu e-mail ou o nome de usuário da pessoa que deseja ajudar
Digite seu e-mail
Título
{errorObject?.key === 'body' && (
@@ -442,6 +448,8 @@ function EditMode({ contentObject, setContentObject, setComponentMode, localStor
Fonte (opcional)
+
{metadata && }
- >
+
);
}
diff --git a/pages/interface/components/EmptyState/index.js b/pages/interface/components/EmptyState/index.js
index 5f64f51f1..6087cb6e0 100644
--- a/pages/interface/components/EmptyState/index.js
+++ b/pages/interface/components/EmptyState/index.js
@@ -1,18 +1,11 @@
-import { Text, Heading, Box, Button } from '@primer/react';
+import { Box, Button, Heading, Text } from '@/TabNewsUI';
import { PlusIcon } from '@primer/octicons-react';
export default function EmptyState(props) {
const { title, description, action, icon: Icon, isLoading } = props;
-
+ if (isLoading) return null;
return (
-
+
{Icon && }
{title}
{description && {description}}
diff --git a/pages/interface/components/Footer/index.js b/pages/interface/components/Footer/index.js
index 5a88077e2..cb768cfd0 100644
--- a/pages/interface/components/Footer/index.js
+++ b/pages/interface/components/Footer/index.js
@@ -1,5 +1,4 @@
-import { Box } from '@primer/react';
-import { Link } from 'pages/interface';
+import { Box, Link } from '@/TabNewsUI';
import { CgTab } from 'react-icons/cg';
export default function Footer(props) {
diff --git a/pages/interface/components/GoToTopButton/index.js b/pages/interface/components/GoToTopButton/index.js
index 9390a0b70..3c7aa9e8e 100644
--- a/pages/interface/components/GoToTopButton/index.js
+++ b/pages/interface/components/GoToTopButton/index.js
@@ -1,5 +1,5 @@
+import { IconButton } from '@/TabNewsUI';
import { ChevronUpIcon } from '@primer/octicons-react';
-import { IconButton } from '@primer/react';
import { useEffect, useState } from 'react';
export default function GoToTopButton() {
diff --git a/pages/interface/components/Head/index.js b/pages/interface/components/Head/index.js
index d5f77a8a0..bf902b2fd 100644
--- a/pages/interface/components/Head/index.js
+++ b/pages/interface/components/Head/index.js
@@ -1,7 +1,7 @@
+import { useMediaQuery } from 'pages/interface';
import webserver from 'infra/webserver.js';
import NextHead from 'next/head';
import { useRouter } from 'next/router';
-import { useMediaQuery } from 'pages/interface/index.js';
const webserverHost = webserver.host;
@@ -18,10 +18,9 @@ export function DefaultHead() {
description: 'Conteúdos com valor concreto para quem trabalha com tecnologia.',
url: `${webserverHost}${router.asPath}`,
type: 'website',
- noIndex: false,
};
- const { type, title, description, image, url, noIndex } = defaultMetadata;
+ const { type, title, description, image, url } = defaultMetadata;
return (
diff --git a/pages/interface/components/Header/index.js b/pages/interface/components/Header/index.js
index e69bfe40f..baee75183 100644
--- a/pages/interface/components/Header/index.js
+++ b/pages/interface/components/Header/index.js
@@ -1,8 +1,21 @@
-import { Header, Box, ActionMenu, ActionList, IconButton, Truncate, Text, Tooltip } from '@primer/react';
-import { PersonFillIcon, HomeIcon, SquareFillIcon } from '@primer/octicons-react';
-import { CgTab } from 'react-icons/cg';
-import { HeaderLink, Link, useUser } from 'pages/interface';
+import {
+ ActionList,
+ ActionMenu,
+ Box,
+ HeaderLink,
+ IconButton,
+ Link,
+ PrimerHeader,
+ Text,
+ ThemeSelector,
+ ThemeSwitcher,
+ Tooltip,
+ Truncate,
+} from '@/TabNewsUI';
+import { HomeIcon, PersonFillIcon, SquareFillIcon } from '@primer/octicons-react';
import { useRouter } from 'next/router';
+import { useUser } from 'pages/interface';
+import { CgTab } from 'react-icons/cg';
export default function HeaderComponent() {
const { user, isLoading, logout } = useUser();
@@ -14,72 +27,78 @@ export default function HeaderComponent() {
};
return (
-
+
);
}
diff --git a/pages/interface/components/Link/index.js b/pages/interface/components/Link/index.js
index 42cb043c2..b277dd881 100644
--- a/pages/interface/components/Link/index.js
+++ b/pages/interface/components/Link/index.js
@@ -1,5 +1,5 @@
+import { NavList, PrimerHeader, PrimerLink } from '@/TabNewsUI';
import NextLink from 'next/link';
-import { Header, Link as PrimerLink, NavList } from '@primer/react';
import { useRouter } from 'next/router';
export function Link({ href, children, ...props }) {
@@ -12,9 +12,9 @@ export function Link({ href, children, ...props }) {
export function HeaderLink({ href, children, ...props }) {
return (
-
+
{children}
-
+
);
}
diff --git a/pages/interface/components/Markdown/index.js b/pages/interface/components/Markdown/index.js
index f47e79f3d..0580c749c 100644
--- a/pages/interface/components/Markdown/index.js
+++ b/pages/interface/components/Markdown/index.js
@@ -1,21 +1,18 @@
-import { Viewer as ByteMdViewer, Editor as ByteMdEditor } from '@bytemd/react';
-import { Box } from '@primer/react';
+import { Box, EditorColors, EditorStyles } from '@/TabNewsUI';
+import { Editor as ByteMdEditor, Viewer as ByteMdViewer } from '@bytemd/react';
import { useEffect, useRef } from 'react';
// ByteMD dependencies:
-import gfmPlugin from '@bytemd/plugin-gfm';
-import highlightSsrPlugin from '@bytemd/plugin-highlight-ssr';
-import mathPlugin from '@bytemd/plugin-math';
-import mermaidPlugin from '@bytemd/plugin-mermaid';
import breaksPlugin from '@bytemd/plugin-breaks';
import gemojiPlugin from '@bytemd/plugin-gemoji';
-import byteMDLocale from 'bytemd/locales/pt_BR.json';
+import gfmPlugin from '@bytemd/plugin-gfm';
import gfmLocale from '@bytemd/plugin-gfm/locales/pt_BR.json';
+import highlightSsrPlugin from '@bytemd/plugin-highlight-ssr';
+import mathPlugin from '@bytemd/plugin-math';
import mathLocale from '@bytemd/plugin-math/locales/pt_BR.json';
+import mermaidPlugin from '@bytemd/plugin-mermaid';
import mermaidLocale from '@bytemd/plugin-mermaid/locales/pt_BR.json';
-import 'bytemd/dist/index.min.css';
-import 'highlight.js/styles/github.css';
-import 'github-markdown-css/github-markdown-light.css';
+import byteMDLocale from 'bytemd/locales/pt_BR.json';
import 'katex/dist/katex.css';
const bytemdPluginList = [
@@ -35,7 +32,8 @@ export default function Viewer({ ...props }) {
}
// Editor is not part of Primer, so error messages and styling need to be created manually
-export function Editor({ isValid, onKeyDown, ...props }) {
+export function Editor({ isValid, onKeyDown, compact, ...props }) {
+ const editorMode = 'split'; // 'tab'
const editorRef = useRef();
useEffect(() => {
@@ -44,56 +42,18 @@ export function Editor({ isValid, onKeyDown, ...props }) {
return () => editorElement?.removeEventListener('keydown', onKeyDown);
}, [onKeyDown]);
+ useEffect(() => {
+ editorRef.current
+ ?.getElementsByClassName('bytemd-toolbar-right')[0]
+ ?.querySelector('[bytemd-tippy-path="2"]')
+ ?.click();
+ }, []);
+
return (
-
-
-
+
+
+
);
}
diff --git a/pages/interface/components/Markdown/styles/index.js b/pages/interface/components/Markdown/styles/index.js
new file mode 100644
index 000000000..9e641a0ef
--- /dev/null
+++ b/pages/interface/components/Markdown/styles/index.js
@@ -0,0 +1,1913 @@
+import { useTheme } from '@/TabNewsUI';
+
+export function EditorColors() {
+ const {
+ theme: { colors, shadows },
+ } = useTheme();
+
+ if (!colors || !shadows) return null;
+
+ return (
+
+ );
+}
+
+export function EditorStyles({ mode, compact }) {
+ return (
+
+ );
+}
+
+export function ViewerStyles() {
+ // based on "highlight.js" and "github-markdown-css"
+
+ const {
+ resolvedColorScheme,
+ theme: { colors, shadows },
+ } = useTheme();
+
+ if (!colors || !shadows) return null;
+
+ return (
+
+ );
+}
diff --git a/pages/interface/components/PasswordInput/index.js b/pages/interface/components/PasswordInput/index.js
index 1e56d2d2b..9ef13a8e5 100644
--- a/pages/interface/components/PasswordInput/index.js
+++ b/pages/interface/components/PasswordInput/index.js
@@ -1,6 +1,6 @@
-import { useEffect, useState } from 'react';
-import { FormControl, TextInput } from '@primer/react';
+import { FormControl, TextInput } from '@/TabNewsUI';
import { EyeClosedIcon, EyeIcon } from '@primer/octicons-react';
+import { useEffect, useState } from 'react';
export default function PasswordInput({ inputRef, id, name, label, errorObject, setErrorObject, ...props }) {
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
@@ -52,7 +52,8 @@ export default function PasswordInput({ inputRef, id, name, label, errorObject,
sx={{ color: 'fg.subtle' }}
/>
}
- sx={{ minHeight: '46px' }}
+ contrast
+ sx={{ minHeight: '46px', pl: 2, '&:focus-within': { backgroundColor: 'canvas.default' } }}
ref={inputRef}
onChange={clearErrors}
onKeyDown={detectCapsLock}
diff --git a/pages/interface/components/PublishedSince/index.js b/pages/interface/components/PublishedSince/index.js
index e0bf210f0..d346bb404 100644
--- a/pages/interface/components/PublishedSince/index.js
+++ b/pages/interface/components/PublishedSince/index.js
@@ -1,6 +1,6 @@
-import { formatDistanceToNowStrict, format } from 'date-fns';
+import { Tooltip } from '@/TabNewsUI';
+import { format, formatDistanceToNowStrict } from 'date-fns';
import { ptBR } from 'date-fns/locale';
-import { Tooltip } from '@primer/react';
import { useEffect, useState } from 'react';
function formatPublishedSince(date) {
diff --git a/pages/interface/components/TabCoinButtons/index.js b/pages/interface/components/TabCoinButtons/index.js
index 002161f6c..b185fc0d6 100644
--- a/pages/interface/components/TabCoinButtons/index.js
+++ b/pages/interface/components/TabCoinButtons/index.js
@@ -1,10 +1,9 @@
-import { useState, useEffect } from 'react';
-import { Box, Text, IconButton, Tooltip } from '@primer/react';
-import { ChevronUpIcon, ChevronDownIcon } from '@primer/octicons-react';
-import { useReward } from 'react-rewards';
+import { Box, IconButton, Text, Tooltip } from '@/TabNewsUI';
+import { ChevronDownIcon, ChevronUpIcon } from '@primer/octicons-react';
import { useRouter } from 'next/router';
-
-import { useUser } from 'pages/interface/index.js';
+import { useUser } from 'pages/interface';
+import { useEffect, useState } from 'react';
+import { useReward } from 'react-rewards';
export default function TabCoinButtons({ content }) {
const router = useRouter();
diff --git a/pages/interface/components/TabNewsUI/index.js b/pages/interface/components/TabNewsUI/index.js
new file mode 100644
index 000000000..197d7d998
--- /dev/null
+++ b/pages/interface/components/TabNewsUI/index.js
@@ -0,0 +1,45 @@
+export { default as Confetti } from '@/Confetti/index.js';
+export { default as Content } from '@/Content/index.js';
+export { default as ContentList } from '@/ContentList/index.js';
+export { default as DefaultLayout } from '@/DefaultLayout/index.js';
+export { default as EmptyState } from '@/EmptyState/index.js';
+export { default as Footer } from '@/Footer/index.js';
+export { default as GoToTopButton } from '@/GoToTopButton/index.js';
+export { default as Header } from '@/Header/index.js';
+export { default as NextLink, HeaderLink, Link, NavItem } from '@/Link';
+export { default as Viewer, Editor } from '@/Markdown/index.js';
+export { EditorColors, EditorStyles, ViewerStyles } from '@/Markdown/styles/index.js';
+export { default as PasswordInput } from '@/PasswordInput/index.js';
+export { default as NextNProgress } from '@/Progressbar/index.js';
+export { default as PublishedSince } from '@/PublishedSince/index.js';
+export { default as TabCoinButtons } from '@/TabCoinButtons/index.js';
+export { default as ThemeProvider } from '@/ThemeProvider/index.js';
+export { default as ThemeSelector, ThemeSwitcher } from '@/ThemeSelector/index.js';
+export {
+ ActionList,
+ ActionMenu,
+ BaseStyles,
+ Box,
+ BranchName,
+ Button,
+ Checkbox,
+ Flash,
+ FormControl,
+ Header as PrimerHeader,
+ Heading,
+ IconButton,
+ Label,
+ LabelGroup,
+ Link as PrimerLink,
+ NavList,
+ Pagehead,
+ SegmentedControl,
+ SSRProvider,
+ Text,
+ TextInput,
+ ThemeProvider as PrimerThemeProvider,
+ Tooltip,
+ Truncate,
+ useConfirm,
+ useTheme,
+} from '@primer/react';
diff --git a/pages/interface/components/ThemeProvider/index.js b/pages/interface/components/ThemeProvider/index.js
new file mode 100644
index 000000000..3526064ad
--- /dev/null
+++ b/pages/interface/components/ThemeProvider/index.js
@@ -0,0 +1,32 @@
+import { BaseStyles, NextNProgress, PrimerThemeProvider, SSRProvider, ViewerStyles } from '@/TabNewsUI';
+import { useEffect, useLayoutEffect, useState } from 'react';
+import { createGlobalStyle } from 'styled-components';
+
+// script to be called before interactive in _document.js
+// document.documentElement.setAttribute('data-no-flash', true)
+const NoFleshGlobalStyle = createGlobalStyle`html[data-no-flash='true']:root {visibility: hidden}`;
+const removeNoFlashStyle = () => setTimeout(() => document.documentElement.removeAttribute('data-no-flash'));
+const useBrowserLayoutEffect = typeof document === 'undefined' ? useEffect : useLayoutEffect;
+
+export default function ThemeProvider({ children, defaultColorMode, ...props }) {
+ const [colorMode, setColorMode] = useState(defaultColorMode === 'night' ? 'night' : 'day');
+
+ useBrowserLayoutEffect(() => {
+ const cachedColorMode = localStorage.getItem('colorMode') || colorMode;
+ setColorMode(cachedColorMode);
+ removeNoFlashStyle();
+ }, []);
+
+ return (
+
+
+
+
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/pages/interface/components/ThemeSelector/index.js b/pages/interface/components/ThemeSelector/index.js
new file mode 100644
index 000000000..4762fa80a
--- /dev/null
+++ b/pages/interface/components/ThemeSelector/index.js
@@ -0,0 +1,66 @@
+import { Box, Button, SegmentedControl, useTheme } from '@/TabNewsUI';
+import { MoonIcon, SunIcon } from '@primer/octicons-react';
+
+export default function ThemeSelector({ ...props }) {
+ const { colorMode, setColorMode } = useTheme();
+
+ const handleChangeColorMode = (mode) => {
+ setColorMode(mode);
+ localStorage.setItem('colorMode', mode);
+ };
+
+ return (
+
+
+ handleChangeColorMode('night')}
+ icon={MoonIcon}
+ size="small"
+ />
+ handleChangeColorMode('auto')}
+ size="small">
+ Auto
+
+ handleChangeColorMode('day')}
+ icon={SunIcon}
+ size="small"
+ />
+
+
+ );
+}
+
+export function ThemeSwitcher({ ...props }) {
+ const { resolvedColorMode: mode, setColorMode } = useTheme();
+
+ const handleSwitchMode = () => {
+ const newMode = mode === 'day' ? 'night' : 'day';
+ setColorMode(newMode);
+ localStorage.setItem('colorMode', newMode);
+ };
+
+ return (
+
+ );
+}
diff --git a/pages/interface/index.js b/pages/interface/index.js
index aa06f8557..ce053499f 100644
--- a/pages/interface/index.js
+++ b/pages/interface/index.js
@@ -1,18 +1,4 @@
-export { default as DefaultLayout } from './components/DefaultLayout/index.js';
-export { default as Header } from './components/Header/index.js';
-export { default as Content } from './components/Content/index.js';
-export { default as ContentList } from './components/ContentList/index.js';
-export { default as Footer } from './components/Footer/index.js';
-export { default as Head } from './components/Head/index.js';
-export { default as TabCoinButtons } from './components/TabCoinButtons/index.js';
-export { default as PublishedSince } from './components/PublishedSince/index.js';
-export { default as EmptyState } from './components/EmptyState/index.js';
-export { default as Confetti } from './components/Confetti/index.js';
-export { default as NextLink, HeaderLink, Link, NavItem } from './components/Link/index.js';
-export { default as GoToTopButton } from './components/GoToTopButton/index.js';
-export { default as Viewer, Editor } from './components/Markdown/index.js';
-export { default as PasswordInput } from './components/PasswordInput/index.js';
-
+export { default as Head, DefaultHead } from './components/Head/index.js';
export { default as useCollapse } from './hooks/useCollapse/index.js';
-export { default as useUser } from './hooks/useUser/index.js';
export { default as useMediaQuery } from './hooks/useMediaQuery/index.js';
+export { default as useUser, UserProvider } from './hooks/useUser/index.js';
diff --git a/pages/login/index.public.js b/pages/login/index.public.js
index 82d4d87aa..8131cf9e5 100644
--- a/pages/login/index.public.js
+++ b/pages/login/index.public.js
@@ -1,7 +1,18 @@
-import { useState, useRef, useEffect } from 'react';
+import {
+ Box,
+ Button,
+ DefaultLayout,
+ Flash,
+ FormControl,
+ Heading,
+ Link,
+ PasswordInput,
+ Text,
+ TextInput,
+} from '@/TabNewsUI';
import { useRouter } from 'next/router';
-import { DefaultLayout, useUser, PasswordInput } from 'pages/interface/index.js';
-import { FormControl, Box, Heading, Button, TextInput, Flash, Link, Text } from '@primer/react';
+import { useUser } from 'pages/interface';
+import { useEffect, useRef, useState } from 'react';
export default function Login() {
return (
@@ -104,7 +115,8 @@ function LoginForm() {
spellCheck={false}
block={true}
aria-label="Seu email"
- sx={{ minHeight: '46px' }}
+ contrast
+ sx={{ minHeight: '46px', px: 2, '&:focus-within': { backgroundColor: 'canvas.default' } }}
/>
{errorObject?.key === 'email' && (
{errorObject.message}
diff --git a/pages/museu/index.public.js b/pages/museu/index.public.js
index f3342daca..dd772d645 100644
--- a/pages/museu/index.public.js
+++ b/pages/museu/index.public.js
@@ -1,5 +1,4 @@
-import { Box, Link, Text } from '@primer/react';
-import { DefaultLayout } from 'pages/interface';
+import { Box, DefaultLayout, PrimerLink, Text } from '@/TabNewsUI';
export default function Page() {
return (
@@ -19,75 +18,75 @@ export default function Page() {
-
- Primeira Home Oficial (Init) feito pelos Membros da Turma
+ Primeira Home Oficial (Init) feito pelos Membros da Turma
-
- Em Construção POC #01 feito por{' '}
- Rodrigo Kulb
+ Em Construção POC #01 feito por{' '}
+ Rodrigo Kulb
-
- Em Construção POC #03 feito por{' '}
- Bruno Familiar
+ Em Construção POC #03 feito por{' '}
+ Bruno Familiar
-
- Home POC #01 feito por{' '}
- Filipe Deschamps
+ Home POC #01 feito por{' '}
+ Filipe Deschamps
-
- Home POC #02 feito por{' '}
- Filipe Deschamps
+ Home POC #02 feito por{' '}
+ Filipe Deschamps
-
- Home POC #03 feito por{' '}
- Filipe Deschamps
+ Home POC #03 feito por{' '}
+ Filipe Deschamps
-
- Home POC #04 feito por{' '}
- Filipe Deschamps
+ Home POC #04 feito por{' '}
+ Filipe Deschamps
-
- Home POC #05 feito por{' '}
- Filipe Deschamps
+ Home POC #05 feito por{' '}
+ Filipe Deschamps
-
- Home POC #06 feito por{' '}
- Filipe Deschamps
+ Home POC #06 feito por{' '}
+ Filipe Deschamps
-
- Home POC #07 feito por{' '}
- Filipe Deschamps
+ Home POC #07 feito por{' '}
+ Filipe Deschamps
-
- Home POC #08 feito por{' '}
- Filipe Deschamps
+ Home POC #08 feito por{' '}
+ Filipe Deschamps
-
- Home POC #09 - Dark Mode feito por{' '}
- Pedro Cruz
+ Home POC #09 - Dark Mode feito por{' '}
+ Pedro Cruz
-
- Home POC #10 feito por{' '}
- Guilhermo Masid
+ Home POC #10 feito por{' '}
+ Guilhermo Masid
-
- Home POC #10 - Mobile feito por{' '}
- Rodrigo Kulb
+ Home POC #10 - Mobile feito por{' '}
+ Rodrigo Kulb
-
- Home POC #11 feito por{' '}
- Pedro Cruz
+ Home POC #11 feito por{' '}
+ Pedro Cruz
-
- Home POC #12 feito por{' '}
- Luan Tonin Galvan
+ Home POC #12 feito por{' '}
+ Luan Tonin Galvan
-
- Post POC #01 feito por{' '}
- Filipe Deschamps
+ Post POC #01 feito por{' '}
+ Filipe Deschamps
-
- Post POC #02 feito por{' '}
- Pedro Cruz
+ Post POC #02 feito por{' '}
+ Pedro Cruz
diff --git a/pages/pagina/[page]/index.public.js b/pages/pagina/[page]/index.public.js
index 28f54297c..6d30118cc 100644
--- a/pages/pagina/[page]/index.public.js
+++ b/pages/pagina/[page]/index.public.js
@@ -1,7 +1,7 @@
-import { DefaultLayout, ContentList } from 'pages/interface/index.js';
-import user from 'models/user.js';
-import content from 'models/content.js';
+import { ContentList, DefaultLayout } from '@/TabNewsUI';
import authorization from 'models/authorization.js';
+import content from 'models/content.js';
+import user from 'models/user.js';
import validator from 'models/validator.js';
export default function Home({ contentListFound, pagination }) {
diff --git a/pages/perfil/confirmar-email/[token].public.js b/pages/perfil/confirmar-email/[token].public.js
index 2973e33fd..a9af7fff8 100644
--- a/pages/perfil/confirmar-email/[token].public.js
+++ b/pages/perfil/confirmar-email/[token].public.js
@@ -1,8 +1,7 @@
+import { Box, Confetti, DefaultLayout, Flash } from '@/TabNewsUI';
import fetch from 'cross-fetch';
-import { Box, Flash } from '@primer/react';
-import { DefaultLayout, Confetti } from 'pages/interface/index.js';
-import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
export default function ActiveUser() {
const router = useRouter();
diff --git a/pages/perfil/index.public.js b/pages/perfil/index.public.js
index 4507a7093..b2d21547e 100644
--- a/pages/perfil/index.public.js
+++ b/pages/perfil/index.public.js
@@ -1,7 +1,18 @@
-import { useState, useRef, useEffect } from 'react';
+import {
+ Box,
+ Button,
+ Checkbox,
+ DefaultLayout,
+ Flash,
+ FormControl,
+ Heading,
+ Link,
+ TextInput,
+ useConfirm,
+} from '@/TabNewsUI';
+import { useUser } from 'pages/interface';
import { useRouter } from 'next/router';
-import { DefaultLayout, useUser, Link } from 'pages/interface/index.js';
-import { FormControl, Box, Heading, Button, TextInput, Checkbox, Flash, useConfirm } from '@primer/react';
+import { useEffect, useRef, useState } from 'react';
export default function EditProfile() {
return (
@@ -168,7 +179,8 @@ function EditProfileForm() {
spellCheck={false}
block={true}
aria-label="Seu nome de usuário"
- sx={{ minHeight: '46px' }}
+ contrast
+ sx={{ minHeight: '46px', px: 2, '&:focus-within': { backgroundColor: 'canvas.default' } }}
/>
{errorObject?.key === 'username' && (
{errorObject.message}
@@ -191,7 +203,8 @@ function EditProfileForm() {
spellCheck={false}
block={true}
aria-label="Seu email"
- sx={{ minHeight: '46px' }}
+ contrast
+ sx={{ minHeight: '46px', px: 2, '&:focus-within': { backgroundColor: 'canvas.default' } }}
/>
{errorObject?.key === 'email' && !errorObject?.type && (
{errorObject.message}
diff --git a/pages/publicar/index.public.js b/pages/publicar/index.public.js
index 5086791b8..f2800fdfe 100644
--- a/pages/publicar/index.public.js
+++ b/pages/publicar/index.public.js
@@ -1,8 +1,8 @@
-import useSWR from 'swr';
+import { Box, Content, DefaultLayout, Flash, Heading, Link } from '@/TabNewsUI';
import { useRouter } from 'next/router';
-import { DefaultLayout, Content, useUser } from 'pages/interface/index.js';
-import { Box, Heading, Flash, Link } from '@primer/react';
+import { useUser } from 'pages/interface';
import { useEffect } from 'react';
+import useSWR from 'swr';
export default function Post() {
const router = useRouter();
diff --git a/pages/recentes/index.public.js b/pages/recentes/index.public.js
index de8412044..81fc5766c 100644
--- a/pages/recentes/index.public.js
+++ b/pages/recentes/index.public.js
@@ -1,7 +1,7 @@
-import { DefaultLayout, ContentList } from 'pages/interface/index.js';
-import user from 'models/user.js';
-import content from 'models/content.js';
+import { ContentList, DefaultLayout } from '@/TabNewsUI';
import authorization from 'models/authorization.js';
+import content from 'models/content.js';
+import user from 'models/user.js';
import validator from 'models/validator.js';
export default function Home({ contentListFound, pagination }) {
diff --git a/pages/recentes/pagina/[page]/index.public.js b/pages/recentes/pagina/[page]/index.public.js
index db202c01c..45c60f580 100644
--- a/pages/recentes/pagina/[page]/index.public.js
+++ b/pages/recentes/pagina/[page]/index.public.js
@@ -1,7 +1,7 @@
-import { DefaultLayout, ContentList } from 'pages/interface/index.js';
-import user from 'models/user.js';
-import content from 'models/content.js';
+import { ContentList, DefaultLayout } from '@/TabNewsUI';
import authorization from 'models/authorization.js';
+import content from 'models/content.js';
+import user from 'models/user.js';
import validator from 'models/validator.js';
export default function Home({ contentListFound, pagination }) {
diff --git a/pages/status/index.public.js b/pages/status/index.public.js
index a8b75e9f6..61b491ce1 100644
--- a/pages/status/index.public.js
+++ b/pages/status/index.public.js
@@ -1,8 +1,6 @@
+import { Box, DefaultLayout, Heading, Label, LabelGroup, Truncate } from '@/TabNewsUI';
+import { Bar, BarChart, ResponsiveContainer, Tooltip, XAxis } from 'recharts';
import useSWR from 'swr';
-import { Box, Heading, Label, LabelGroup, Truncate } from '@primer/react';
-import { ResponsiveContainer, BarChart, Bar, Tooltip, XAxis } from 'recharts';
-
-import { DefaultLayout } from 'pages/interface/index.js';
export default function Page() {
const { data: statusObject, isLoading: statusObjectIsLoading } = useSWR('/api/v1/status', {
diff --git a/pages/termos-de-uso/index.public.js b/pages/termos-de-uso/index.public.js
index da0d5d368..7adf7126b 100644
--- a/pages/termos-de-uso/index.public.js
+++ b/pages/termos-de-uso/index.public.js
@@ -1,7 +1,4 @@
-import { Box, Heading } from '@primer/react';
-import { Viewer } from 'pages/interface';
-
-import { DefaultLayout } from 'pages/interface/index.js';
+import { Box, DefaultLayout, Heading, Viewer } from '@/TabNewsUI';
export default function Page() {
const body = `Ao utilizar o TabNews você está de acordo com os seguintes termos: