Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
265 changes: 171 additions & 94 deletions README.md

Large diffs are not rendered by default.

523 changes: 523 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
"src/social-share-button.css",
"src/social-share-button-react.jsx",
"src/social-share-analytics.js",
"src/utils/extractContent.js",
"README.md",
"LICENSE"
],
"scripts": {
"lint": "eslint src/**/*.{js,jsx} --max-warnings=0",
"lint:fix": "eslint src/**/*.{js,jsx} --fix",
"format": "prettier --write \"**/*.{js,jsx,json,css,md,html}\"",
"format:check": "prettier --check \"**/*.{js,jsx,json,css,md,html}\""
"format:check": "prettier --check \"**/*.{js,jsx,json,css,md,html}\"",
"test": "node --test tests/**/*.test.js"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -44,6 +46,7 @@
"@eslint/js": "^9.39.4",
"eslint": "^9.39.4",
"globals": "^17.4.0",
"jsdom": "^29.0.0",
"prettier": "^3.2.4"
},
"type": "module"
Expand Down
66 changes: 38 additions & 28 deletions src/social-share-button-react.jsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,41 @@
import { useEffect, useRef } from "react";
import { useEffect, useRef } from 'react';

export const SocialShareButton = ({
url,
title,
description = "",
description = '',
hashtags = [],
via = "",
platforms = [
"whatsapp",
"facebook",
"twitter",
"linkedin",
"telegram",
"reddit",
],
theme = "dark",
buttonText = "Share",
customClass = "",
via = '',
platforms = ['whatsapp', 'facebook', 'twitter', 'linkedin', 'telegram', 'reddit'],
theme = 'dark',
buttonText = 'Share',
customClass = '',
onShare = null,
onCopy = null,
buttonStyle = "default",
modalPosition = "center",
buttonStyle = 'default',
modalPosition = 'center',
// Content auto-detection β€” set to false when all props are always provided.
autoDetect = true,
// Analytics props β€” the library itself never collects data.
// Provide any combination to connect your own analytics tools.
analytics = true, // set to false to disable all event emission
onAnalytics = null, // (payload) => void β€” direct callback hook
analyticsPlugins = [], // array of adapter instances (see social-share-analytics.js)
componentId = null, // optional string identifier for this instance
debug = false, // log events to console during development
analytics = true, // set to false to disable all event emission
onAnalytics = null, // (payload) => void β€” direct callback hook
analyticsPlugins = [], // array of adapter instances (see social-share-analytics.js)
componentId = null, // optional string identifier for this instance
debug = false, // log events to console during development
}) => {
const containerRef = useRef(null);
const shareButtonRef = useRef(null);

// Auto-detect current URL and title if not provided
const currentUrl =
url || (typeof window !== "undefined" ? window.location.href : "");
const currentTitle =
title || (typeof document !== "undefined" ? document.title : "");
// Auto-detect current URL and title if not provided.
// When autoDetect is enabled, the vanilla SocialShareButton constructor
// handles deeper detection (og:title, meta description, semantic HTML).
const currentUrl = url || (typeof window !== 'undefined' ? window.location.href : '');
const currentTitle = title || (typeof document !== 'undefined' ? document.title : '');

useEffect(() => {
if (containerRef.current && !shareButtonRef.current) {
if (typeof window !== "undefined" && window.SocialShareButton) {
if (typeof window !== 'undefined' && window.SocialShareButton) {
shareButtonRef.current = new window.SocialShareButton({
container: containerRef.current,
url: currentUrl,
Expand All @@ -56,6 +51,7 @@ export const SocialShareButton = ({
onCopy,
buttonStyle,
modalPosition,
autoDetect,
analytics,
onAnalytics,
analyticsPlugins,
Expand All @@ -73,9 +69,21 @@ export const SocialShareButton = ({
};
}, []);

// Update options when props change (including URL from route changes)
// Update options when props change (including URL from route changes).
// Also bust the content-detection cache so the new page's metadata is used.
useEffect(() => {
if (shareButtonRef.current) {
// Invalidate detection cache on every route/prop change so the new
// page content is picked up when autoDetect is enabled.
if (
autoDetect &&
typeof window !== 'undefined' &&
window.SocialShareButton &&
typeof window.SocialShareButton.clearContentCache === 'function'
) {
window.SocialShareButton.clearContentCache();
}
Comment on lines +83 to +102
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Cache clearing before updateOptions is ineffective β€” detection not re-run.

The intent here is good: clear the cache so fresh page metadata can be detected on route changes. However, as noted in the social-share-button.js review, updateOptions() does not re-run _ContentDetector.extract(). Auto-detection only happens once in the constructor.

This means:

  1. clearContentCache() clears the cache βœ“
  2. updateOptions() merges new options but uses the original auto-detected values βœ—
  3. New page metadata is never picked up βœ—

This should be addressed in social-share-button.js by having updateOptions optionally re-run detection.

πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/social-share-button-react.jsx` around lines 72 - 85, clearContentCache()
is being called but updateOptions() never re-runs content detection (the
detector only runs in the constructor), so auto-detected metadata isn't
refreshed; change updateOptions in social-share-button.js (the method named
updateOptions) to accept an option/flag to force re-running the content detector
(invoke _ContentDetector.extract() when autoDetect is true or when the new flag
is set) and then, in social-share-button-react.jsx where you clear the cache
(inside the useEffect with shareButtonRef.current and autoDetect), call
updateOptions with that flag so detection is executed after cache clear.


shareButtonRef.current.updateOptions({
url: currentUrl,
title: currentTitle,
Expand All @@ -90,6 +98,7 @@ export const SocialShareButton = ({
onCopy,
buttonStyle,
modalPosition,
autoDetect,
analytics,
onAnalytics,
analyticsPlugins,
Expand All @@ -111,6 +120,7 @@ export const SocialShareButton = ({
onCopy,
buttonStyle,
modalPosition,
autoDetect,
analytics,
onAnalytics,
analyticsPlugins,
Expand Down
Loading