diff --git a/packages/docusaurus-commenting-system/README.md b/packages/docusaurus-commenting-system/README.md new file mode 100644 index 00000000..c9a1ea58 --- /dev/null +++ b/packages/docusaurus-commenting-system/README.md @@ -0,0 +1,117 @@ +# Docusaurus commenting system plugin + +The Docusaurus Commenting System plugin allows to add a realtime commenting system to your Docusaurus project. It uses Supabase as a backend and GitHub as an authentication provider. + +## Installation + +### Supabase setup + +1. Create a Supabase project. +2. Activate the GitHub authentication provider (Authentification > Providers). +3. In the SQL Editor, run the following queries: + + - To create the `profiles` table: + + ```sql + create table + public.profiles ( + id uuid not null, + user_name text null, + constraint profiles_pkey primary key (id), + constraint profiles_id_fkey foreign key (id) references auth.users (id) on delete cascade + ) tablespace pg_default; + ``` + + - To create the `comments` table: + + ```sql + create table + public.comments ( + id bigint generated by default as identity, + created_at timestamp without time zone not null default now(), + text text not null, + page_path text not null, + author_id uuid not null default auth.uid (), + constraint comment_pkey primary key (id), + constraint comment_id_key unique (id), + constraint comments_author_id_fkey foreign key (author_id) references profiles (id) + ) tablespace pg_default; + ``` + + - To create a function and a trigger to automatically fill the `profiles` table when a new user authenticates with GitHub for the first time: + + ```sql + -- inserts a row into public.profiles + create function public.handle_new_user() + returns trigger + language plpgsql + security definer set search_path = public + as $$ + begin + insert into public.profiles (id, user_name) + values (new.id, new.raw_user_meta_data ->> 'user_name'); + return new; + end; + + + $$; + + -- trigger the function every time a user is created + create trigger on_auth_user_created + after insert on auth.users + for each row execute procedure public.handle_new_user(); + + ``` + +4. Activate Realtime on the `comments` table. +5. Go to Database > Schema Visualizer and make sure that your database schema looks like this: + ![Supabase database schema](https://iili.io/JRKk0v9.png) +6. Please consider adding RLS (Row Level Security) policies to your tables. You should allow only authenticated users to INSERT on the `comments` table and you can add public read access to the `profiles` and `comments` tables. + +### Docusaurus setup + +1. Add the plugin to your Docusaurus project: `yarn add @acid-info/docusaurus-commenting-system`. +2. Add the plugin to your `docusaurus.config.js` file: + +```js +const config = { + // other config fields..., + plugins: [ + // other plugins..., + [ + '@acid-info/docusaurus-commenting-system', + { + supabaseUrl: process.env.SUPABASE_URL, + supabaseAnonKey: process.env.SUPABASE_ANON_KEY, + }, + ], + ], +} +``` + +3. Create a `.env` file at the root of your project and add the following environment variables. They are your Supabase Project URL and Supabase Public API Key, never put a secret key here. + +``` +SUPABASE_URL=https://example.supabase.co +SUPABASE_ANON_KEY=example.anon.key +``` + +4. Add the `CommentingSystem` component to your pages. Here is an example in a mdx docs page: + +```mdx +## // docs/example.mdx + +## title: Example + +import { CommentingSystem } from '@acid-info/docusaurus-commenting-system/lib/client/' + +# Example doc page + +This is an example doc page with the commenting system at the bottom of it. + +# Comments section + + +``` + +`N.B.:` The commenting section is unique to each individual page URL. This means that the comments you see on one page are specific to that page only and are not shared or displayed on other pages. Each page has its own separate set of comments. diff --git a/packages/docusaurus-commenting-system/package.json b/packages/docusaurus-commenting-system/package.json new file mode 100644 index 00000000..a8ddd26e --- /dev/null +++ b/packages/docusaurus-commenting-system/package.json @@ -0,0 +1,32 @@ +{ + "name": "@acid-info/docusaurus-commenting-system", + "version": "1.0.0-alpha", + "description": "Docusaurus docs commenting system plugin", + "main": "lib/index.js", + "repository": { + "type": "git", + "url": "https://github.com/acid-info/logos-docusaurus-plugins.git", + "directory": "packages/docusaurus-commenting-system" + }, + "scripts": { + "build": "tsc --build && node scripts/copy-scss.js", + "watch": "tsc --build --watch", + "prepublishOnly": "yarn build" + }, + "dependencies": { + "@acid-info/lsd-react": "^0.1.0-beta.1", + "@docusaurus/types": "^3.0.1", + "@supabase/supabase-js": "^2.39.1", + "date-fns": "^3.0.6", + "react": "^17.0.2", + "react-dom": "^17.0.2" + }, + "devDependencies": { + "copyfiles": "^2.4.1", + "css-loader": "^6.8.1", + "sass": "^1.69.5", + "sass-loader": "^13.3.2", + "style-loader": "^3.3.3" + }, + "license": "MIT" +} diff --git a/packages/docusaurus-commenting-system/scripts/copy-scss.js b/packages/docusaurus-commenting-system/scripts/copy-scss.js new file mode 100644 index 00000000..328a92f6 --- /dev/null +++ b/packages/docusaurus-commenting-system/scripts/copy-scss.js @@ -0,0 +1,37 @@ +const fs = require('fs') +const path = require('path') +const copyfiles = require('copyfiles') + +function copySCSS(srcDir, destDir) { + fs.readdir(srcDir, { withFileTypes: true }, (err, entries) => { + if (err) { + console.error(err) + return + } + + entries.forEach((entry) => { + const srcPath = path.join(srcDir, entry.name) + const destPath = path.join(destDir, entry.name) + + if (entry.isDirectory()) { + // Recursive call for directories + copySCSS(srcPath, destPath) + } else if (path.extname(entry.name) === '.scss') { + // Copying .scss files + copyfiles([srcPath, path.dirname(destPath)], { up: true }, (err) => { + if (err) console.error(err) + }) + } + }) + }) +} + +const srcClientPath = path.join(__dirname, '../src/client') +const libClientPath = path.join(__dirname, '../lib/client') + +// Ensure the destination directory exists +if (!fs.existsSync(libClientPath)) { + fs.mkdirSync(libClientPath, { recursive: true }) +} + +copySCSS(srcClientPath, libClientPath) diff --git a/packages/docusaurus-commenting-system/src/client/components/Comment/Comment.module.scss b/packages/docusaurus-commenting-system/src/client/components/Comment/Comment.module.scss new file mode 100644 index 00000000..6182e512 --- /dev/null +++ b/packages/docusaurus-commenting-system/src/client/components/Comment/Comment.module.scss @@ -0,0 +1,18 @@ +.commentHeader { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.3rem; + + .username { + font-weight: bold; + } + + .date { + font-weight: lighter; + } +} + +.commentText { + white-space: pre-line; +} diff --git a/packages/docusaurus-commenting-system/src/client/components/Comment/Comment.tsx b/packages/docusaurus-commenting-system/src/client/components/Comment/Comment.tsx new file mode 100644 index 00000000..05b6800b --- /dev/null +++ b/packages/docusaurus-commenting-system/src/client/components/Comment/Comment.tsx @@ -0,0 +1,25 @@ +import React from 'react' +import { CardBody } from '@acid-info/lsd-react' +import styles from './Comment.module.scss' + +export type CommentProps = { + username: string + comment: string + date: string +} + +export const Comment: React.FC = ({ + username, + comment, + date, +}) => { + return ( + +
+ {username} + {date} +
+
{comment}
+
+ ) +} diff --git a/packages/docusaurus-commenting-system/src/client/components/Comment/index.ts b/packages/docusaurus-commenting-system/src/client/components/Comment/index.ts new file mode 100644 index 00000000..85a5c820 --- /dev/null +++ b/packages/docusaurus-commenting-system/src/client/components/Comment/index.ts @@ -0,0 +1 @@ +export * from './Comment' diff --git a/packages/docusaurus-commenting-system/src/client/components/WriteComment/WriteComment.module.scss b/packages/docusaurus-commenting-system/src/client/components/WriteComment/WriteComment.module.scss new file mode 100644 index 00000000..93e8269e --- /dev/null +++ b/packages/docusaurus-commenting-system/src/client/components/WriteComment/WriteComment.module.scss @@ -0,0 +1,36 @@ +.textarea { + width: 100%; + min-width: 100%; + max-width: 100%; + + &:disabled { + cursor: not-allowed; + } +} + +.actionContainer { + display: flex; + justify-content: flex-end; + margin-top: 0.5rem; +} + +.githubBtnLabel { + display: flex; + column-gap: 5px; + align-items: center; + justify-content: center; + + &::before { + content: ''; + width: 16px; + height: 16px; + display: flex; + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") + no-repeat; + } + + html[data-theme='dark'] &::before { + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") + no-repeat; + } +} diff --git a/packages/docusaurus-commenting-system/src/client/components/WriteComment/WriteComment.tsx b/packages/docusaurus-commenting-system/src/client/components/WriteComment/WriteComment.tsx new file mode 100644 index 00000000..5b95f33a --- /dev/null +++ b/packages/docusaurus-commenting-system/src/client/components/WriteComment/WriteComment.tsx @@ -0,0 +1,49 @@ +import React, { useState } from 'react' +import { CardBody, Button } from '@acid-info/lsd-react' +import styles from './WriteComment.module.scss' + +export type WriteCommentProps = { + handleSend: (comment: string) => void + handleSignIn: () => void + isSignedIn?: boolean +} + +export const WriteComment: React.FC = ({ + handleSend, + handleSignIn, + isSignedIn = false, +}) => { + const [comment, setComment] = useState('') + + const onSendClick = () => { + const commentToSend = comment.trim() + if (commentToSend) { + handleSend(commentToSend) + setComment('') + } + } + + return ( + +