mirror of
https://github.com/WenPai-org/git-embed-feicode.git
synced 2025-08-03 03:18:41 +08:00
Add support for custom Git platforms and UI enhancements
This update introduces support for self-hosted Git platforms (Gitea, Forgejo, GitLab, and custom services) with custom domain and site name options. It adds new UI controls for button size, style, and additional action buttons (Issues, Forks), and implements new card styles (gradient, glassmorphism) and platform-specific color badges. The PHP backend now normalizes API calls and repository data for multiple platforms, and the CSS is updated for new styles and platform-specific elements.
This commit is contained in:
parent
0c4746d0d3
commit
3b10f2574f
3 changed files with 598 additions and 73 deletions
141
block.js
141
block.js
|
@ -31,6 +31,14 @@
|
|||
type: 'string',
|
||||
default: 'github'
|
||||
},
|
||||
customDomain: {
|
||||
type: 'string',
|
||||
default: ''
|
||||
},
|
||||
customSiteName: {
|
||||
type: 'string',
|
||||
default: ''
|
||||
},
|
||||
owner: {
|
||||
type: 'string',
|
||||
default: ''
|
||||
|
@ -85,7 +93,19 @@
|
|||
},
|
||||
buttonStyle: {
|
||||
type: 'string',
|
||||
default: 'primary'
|
||||
default: 'default'
|
||||
},
|
||||
buttonSize: {
|
||||
type: 'string',
|
||||
default: 'medium'
|
||||
},
|
||||
showIssuesButton: {
|
||||
type: 'boolean',
|
||||
default: false
|
||||
},
|
||||
showForksButton: {
|
||||
type: 'boolean',
|
||||
default: false
|
||||
},
|
||||
alignment: {
|
||||
type: 'string',
|
||||
|
@ -96,9 +116,9 @@
|
|||
edit: function(props) {
|
||||
const { attributes, setAttributes } = props;
|
||||
const {
|
||||
platform, owner, repo, showDescription, showStats, showLanguage,
|
||||
showActions, showViewButton, showCloneButton, showDownloadButton,
|
||||
showAvatar, showSiteInfo, avatarSize, cardStyle, buttonStyle, alignment
|
||||
platform, customDomain, customSiteName, owner, repo, showDescription, showStats, showLanguage,
|
||||
showActions, showViewButton, showCloneButton, showDownloadButton, showIssuesButton, showForksButton,
|
||||
showAvatar, showSiteInfo, avatarSize, cardStyle, buttonStyle, buttonSize, alignment
|
||||
} = attributes;
|
||||
|
||||
const [repoData, setRepoData] = useState(null);
|
||||
|
@ -115,12 +135,19 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if ((platform === 'gitea' || platform === 'forgejo' || platform === 'gitlab' || platform === 'custom') && !customDomain) {
|
||||
setError(`Please enter custom domain for ${platform.charAt(0).toUpperCase() + platform.slice(1)}`);
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
setError('');
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'git_embed_fetch');
|
||||
formData.append('platform', platform);
|
||||
formData.append('customDomain', customDomain);
|
||||
formData.append('customSiteName', customSiteName);
|
||||
formData.append('owner', owner);
|
||||
formData.append('repo', repo);
|
||||
formData.append('nonce', gitEmbedAjax.nonce);
|
||||
|
@ -148,10 +175,10 @@
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (owner && repo) {
|
||||
if (owner && repo && (platform === 'github' || (platform !== 'github' && customDomain))) {
|
||||
fetchRepoData();
|
||||
}
|
||||
}, [owner, repo, platform]);
|
||||
}, [owner, repo, platform, customDomain, customSiteName]);
|
||||
|
||||
const renderPreview = () => {
|
||||
if (loading) {
|
||||
|
@ -180,15 +207,19 @@
|
|||
|
||||
const cardClass = `git-embed-card${cardStyle !== 'default' ? ` git-embed-card-${cardStyle}` : ''}`;
|
||||
const avatarClass = `git-embed-avatar git-embed-avatar-${avatarSize}`;
|
||||
const buttonClass = `git-embed-button-${buttonSize}`;
|
||||
const downloadUrl = repoData.archive_url ?
|
||||
repoData.archive_url.replace('{archive_format}', 'zipball').replace('{/ref}', '/main') : '';
|
||||
|
||||
return el('div', { className: cardClass },
|
||||
showSiteInfo && repoData.site_info && el('div', { className: 'git-embed-site-info' },
|
||||
showSiteInfo && repoData.site_info && el('div', {
|
||||
className: `git-embed-site-info platform-${repoData.platform || 'github'}`
|
||||
},
|
||||
el('img', {
|
||||
src: repoData.site_info.favicon,
|
||||
alt: repoData.site_info.name,
|
||||
className: 'git-embed-site-favicon'
|
||||
className: 'git-embed-site-favicon',
|
||||
onError: (e) => e.target.style.display = 'none'
|
||||
}),
|
||||
el('span', { className: 'git-embed-site-name' },
|
||||
el('a', {
|
||||
|
@ -226,9 +257,14 @@
|
|||
)
|
||||
)
|
||||
),
|
||||
showLanguage && repoData.language && el('span', { className: 'git-embed-language' },
|
||||
el('span', { className: 'dashicons dashicons-editor-code' }),
|
||||
repoData.language
|
||||
el('div', { className: 'git-embed-meta-section' },
|
||||
showLanguage && repoData.language && el('span', { className: 'git-embed-language' },
|
||||
el('span', { className: 'dashicons dashicons-editor-code' }),
|
||||
repoData.language
|
||||
),
|
||||
el('span', {
|
||||
className: `git-embed-platform-badge platform-${repoData.platform || 'github'}`
|
||||
}, repoData.platform ? repoData.platform.toUpperCase() : 'GITHUB')
|
||||
)
|
||||
),
|
||||
|
||||
|
@ -254,11 +290,11 @@
|
|||
el('span', { className: 'git-embed-stat-value' }, repoData.open_issues_count.toLocaleString())
|
||||
)
|
||||
),
|
||||
showActions && (showViewButton || showCloneButton || showDownloadButton) &&
|
||||
showActions && (showViewButton || showCloneButton || showDownloadButton || showIssuesButton || showForksButton) &&
|
||||
el('div', { className: 'git-embed-actions' },
|
||||
showViewButton && el('a', {
|
||||
href: repoData.html_url,
|
||||
className: `git-embed-button git-embed-button-${buttonStyle}`,
|
||||
className: `git-embed-button git-embed-button-${buttonStyle} ${buttonClass}`,
|
||||
target: '_blank',
|
||||
rel: 'noopener'
|
||||
},
|
||||
|
@ -266,7 +302,7 @@
|
|||
'View Repository'
|
||||
),
|
||||
showCloneButton && el('span', {
|
||||
className: 'git-embed-button git-embed-button-secondary',
|
||||
className: `git-embed-button git-embed-button-secondary ${buttonClass}`,
|
||||
title: `Clone URL: ${repoData.clone_url}`
|
||||
},
|
||||
el('span', { className: 'dashicons dashicons-admin-page' }),
|
||||
|
@ -274,11 +310,29 @@
|
|||
),
|
||||
showDownloadButton && el('a', {
|
||||
href: downloadUrl,
|
||||
className: 'git-embed-button git-embed-button-secondary',
|
||||
className: `git-embed-button git-embed-button-secondary ${buttonClass}`,
|
||||
download: `${repoData.name}.zip`
|
||||
},
|
||||
el('span', { className: 'dashicons dashicons-download' }),
|
||||
'Download ZIP'
|
||||
),
|
||||
showIssuesButton && el('a', {
|
||||
href: `${repoData.html_url}/issues`,
|
||||
className: `git-embed-button git-embed-button-outline ${buttonClass}`,
|
||||
target: '_blank',
|
||||
rel: 'noopener'
|
||||
},
|
||||
el('span', { className: 'dashicons dashicons-editor-help' }),
|
||||
`Issues (${repoData.open_issues_count.toLocaleString()})`
|
||||
),
|
||||
showForksButton && el('a', {
|
||||
href: `${repoData.html_url}/forks`,
|
||||
className: `git-embed-button git-embed-button-outline ${buttonClass}`,
|
||||
target: '_blank',
|
||||
rel: 'noopener'
|
||||
},
|
||||
el('span', { className: 'dashicons dashicons-networking' }),
|
||||
`Forks (${repoData.forks_count.toLocaleString()})`
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -300,9 +354,28 @@
|
|||
label: __('Platform', 'git-embed-feicode'),
|
||||
value: platform,
|
||||
options: [
|
||||
{ label: 'GitHub', value: 'github' }
|
||||
{ label: 'GitHub', value: 'github' },
|
||||
{ label: 'Gitea', value: 'gitea' },
|
||||
{ label: 'Forgejo', value: 'forgejo' },
|
||||
{ label: 'GitLab (Self-hosted)', value: 'gitlab' },
|
||||
{ label: 'Custom Git Service', value: 'custom' }
|
||||
],
|
||||
onChange: (value) => setAttributes({ platform: value })
|
||||
onChange: (value) => setAttributes({ platform: value }),
|
||||
help: platform !== 'github' ? 'Self-hosted Git service requires custom domain' : ''
|
||||
}),
|
||||
(platform !== 'github') && el(TextControl, {
|
||||
label: __('Custom Domain', 'git-embed-feicode'),
|
||||
value: customDomain,
|
||||
onChange: (value) => setAttributes({ customDomain: value }),
|
||||
placeholder: 'e.g. git.example.com',
|
||||
help: `Enter the domain of your ${platform.charAt(0).toUpperCase() + platform.slice(1)} instance`
|
||||
}),
|
||||
(platform !== 'github') && el(TextControl, {
|
||||
label: __('Custom Site Name (Optional)', 'git-embed-feicode'),
|
||||
value: customSiteName,
|
||||
onChange: (value) => setAttributes({ customSiteName: value }),
|
||||
placeholder: 'e.g. Company Git',
|
||||
help: 'Override the automatically detected site name'
|
||||
}),
|
||||
el(TextControl, {
|
||||
label: __('Repository Owner', 'git-embed-feicode'),
|
||||
|
@ -319,7 +392,8 @@
|
|||
el(Button, {
|
||||
isPrimary: true,
|
||||
onClick: fetchRepoData,
|
||||
disabled: loading || !owner || !repo
|
||||
disabled: loading || !owner || !repo ||
|
||||
(platform !== 'github' && !customDomain)
|
||||
}, loading ? 'Fetching...' : 'Fetch Repository')
|
||||
),
|
||||
el(PanelBody, {
|
||||
|
@ -389,16 +463,41 @@
|
|||
onChange: (value) => setAttributes({ showDownloadButton: value }),
|
||||
disabled: !showActions
|
||||
}),
|
||||
el(ToggleControl, {
|
||||
label: __('Show Issues Button', 'git-embed-feicode'),
|
||||
checked: showIssuesButton,
|
||||
onChange: (value) => setAttributes({ showIssuesButton: value }),
|
||||
disabled: !showActions
|
||||
}),
|
||||
el(ToggleControl, {
|
||||
label: __('Show Forks Button', 'git-embed-feicode'),
|
||||
checked: showForksButton,
|
||||
onChange: (value) => setAttributes({ showForksButton: value }),
|
||||
disabled: !showActions
|
||||
}),
|
||||
el(SelectControl, {
|
||||
label: __('Button Style', 'git-embed-feicode'),
|
||||
value: buttonStyle,
|
||||
options: [
|
||||
{ label: 'Default', value: 'default' },
|
||||
{ label: 'Primary (Green)', value: 'primary' },
|
||||
{ label: 'Secondary (Gray)', value: 'secondary' },
|
||||
{ label: 'Outline', value: 'outline' }
|
||||
{ label: 'Outline', value: 'outline' },
|
||||
{ label: 'Ghost', value: 'ghost' }
|
||||
],
|
||||
onChange: (value) => setAttributes({ buttonStyle: value }),
|
||||
disabled: !showActions
|
||||
}),
|
||||
el(SelectControl, {
|
||||
label: __('Button Size', 'git-embed-feicode'),
|
||||
value: buttonSize,
|
||||
options: [
|
||||
{ label: 'Small', value: 'small' },
|
||||
{ label: 'Medium', value: 'medium' },
|
||||
{ label: 'Large', value: 'large' }
|
||||
],
|
||||
onChange: (value) => setAttributes({ buttonSize: value }),
|
||||
disabled: !showActions
|
||||
})
|
||||
),
|
||||
el(PanelBody, {
|
||||
|
@ -412,7 +511,9 @@
|
|||
{ label: 'Default', value: 'default' },
|
||||
{ label: 'Minimal', value: 'minimal' },
|
||||
{ label: 'Bordered', value: 'bordered' },
|
||||
{ label: 'Shadow', value: 'shadow' }
|
||||
{ label: 'Shadow', value: 'shadow' },
|
||||
{ label: 'Gradient', value: 'gradient' },
|
||||
{ label: 'Glassmorphism', value: 'glass' }
|
||||
],
|
||||
onChange: (value) => setAttributes({ cardStyle: value })
|
||||
})
|
||||
|
|
|
@ -43,6 +43,14 @@ class GitEmbedFeiCode {
|
|||
'type' => 'string',
|
||||
'default' => 'github'
|
||||
],
|
||||
'customDomain' => [
|
||||
'type' => 'string',
|
||||
'default' => ''
|
||||
],
|
||||
'customSiteName' => [
|
||||
'type' => 'string',
|
||||
'default' => ''
|
||||
],
|
||||
'owner' => [
|
||||
'type' => 'string',
|
||||
'default' => ''
|
||||
|
@ -85,7 +93,19 @@ class GitEmbedFeiCode {
|
|||
],
|
||||
'buttonStyle' => [
|
||||
'type' => 'string',
|
||||
'default' => 'primary'
|
||||
'default' => 'default'
|
||||
],
|
||||
'buttonSize' => [
|
||||
'type' => 'string',
|
||||
'default' => 'medium'
|
||||
],
|
||||
'showIssuesButton' => [
|
||||
'type' => 'boolean',
|
||||
'default' => false
|
||||
],
|
||||
'showForksButton' => [
|
||||
'type' => 'boolean',
|
||||
'default' => false
|
||||
],
|
||||
'showAvatar' => [
|
||||
'type' => 'boolean',
|
||||
|
@ -131,12 +151,18 @@ class GitEmbedFeiCode {
|
|||
$owner = sanitize_text_field($attributes['owner'] ?? '');
|
||||
$repo = sanitize_text_field($attributes['repo'] ?? '');
|
||||
$platform = sanitize_text_field($attributes['platform'] ?? 'github');
|
||||
$custom_domain = sanitize_text_field($attributes['customDomain'] ?? '');
|
||||
$custom_site_name = sanitize_text_field($attributes['customSiteName'] ?? '');
|
||||
|
||||
if (empty($owner) || empty($repo)) {
|
||||
return '<div class="git-embed-error">Repository information required</div>';
|
||||
}
|
||||
|
||||
$repo_data = $this->fetch_repository_data($platform, $owner, $repo);
|
||||
if (in_array($platform, ['gitea', 'forgejo', 'gitlab', 'custom']) && empty($custom_domain)) {
|
||||
return '<div class="git-embed-error">Custom domain required for ' . ucfirst($platform) . '</div>';
|
||||
}
|
||||
|
||||
$repo_data = $this->fetch_repository_data($platform, $owner, $repo, $custom_domain, $custom_site_name);
|
||||
|
||||
if (!$repo_data) {
|
||||
return '<div class="git-embed-error">Failed to fetch repository data</div>';
|
||||
|
@ -145,24 +171,25 @@ class GitEmbedFeiCode {
|
|||
return $this->render_repository_card($repo_data, $attributes);
|
||||
}
|
||||
|
||||
private function fetch_repository_data(string $platform, string $owner, string $repo): ?array {
|
||||
if ($platform !== 'github') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cache_key = "git_embed_{$platform}_{$owner}_{$repo}";
|
||||
private function fetch_repository_data(string $platform, string $owner, string $repo, string $custom_domain = '', string $custom_site_name = ''): ?array {
|
||||
$cache_key = "git_embed_{$platform}_{$owner}_{$repo}" . ($custom_domain ? "_{$custom_domain}" : '') . ($custom_site_name ? "_{$custom_site_name}" : '');
|
||||
$cached = get_transient($cache_key);
|
||||
|
||||
if ($cached !== false) {
|
||||
return $cached;
|
||||
}
|
||||
|
||||
$url = "https://api.github.com/repos/{$owner}/{$repo}";
|
||||
$api_config = $this->get_api_config($platform, $custom_domain, $custom_site_name);
|
||||
if (!$api_config) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$url = $api_config['api_url'] . "/repos/{$owner}/{$repo}";
|
||||
$response = wp_remote_get($url, [
|
||||
'timeout' => 15,
|
||||
'headers' => [
|
||||
'User-Agent' => 'Git-Embed-FeiCode/1.0',
|
||||
'Accept' => 'application/vnd.github.v3+json'
|
||||
'Accept' => 'application/json'
|
||||
]
|
||||
]);
|
||||
|
||||
|
@ -176,38 +203,224 @@ class GitEmbedFeiCode {
|
|||
return null;
|
||||
}
|
||||
|
||||
$repo_data = [
|
||||
'name' => $data['name'],
|
||||
'full_name' => $data['full_name'],
|
||||
'description' => $data['description'],
|
||||
'html_url' => $data['html_url'],
|
||||
'language' => $data['language'],
|
||||
'stargazers_count' => $data['stargazers_count'],
|
||||
'forks_count' => $data['forks_count'],
|
||||
'open_issues_count' => $data['open_issues_count'],
|
||||
'clone_url' => $data['clone_url'],
|
||||
'archive_url' => $data['archive_url'],
|
||||
'owner' => [
|
||||
'login' => $data['owner']['login'],
|
||||
'avatar_url' => $data['owner']['avatar_url'],
|
||||
'html_url' => $data['owner']['html_url'],
|
||||
'type' => $data['owner']['type']
|
||||
],
|
||||
'site_info' => [
|
||||
'name' => 'GitHub',
|
||||
'url' => 'https://github.com',
|
||||
'favicon' => 'https://github.com/favicon.ico',
|
||||
'color' => '#24292f'
|
||||
]
|
||||
];
|
||||
$repo_data = $this->normalize_repository_data($data, $platform, $api_config);
|
||||
|
||||
set_transient($cache_key, $repo_data, DAY_IN_SECONDS);
|
||||
|
||||
$this->cache_avatar($repo_data['owner']['avatar_url']);
|
||||
if (!empty($repo_data['owner']['avatar_url'])) {
|
||||
$this->cache_avatar($repo_data['owner']['avatar_url']);
|
||||
}
|
||||
|
||||
return $repo_data;
|
||||
}
|
||||
|
||||
private function get_api_config(string $platform, string $custom_domain = '', string $custom_site_name = ''): ?array {
|
||||
switch ($platform) {
|
||||
case 'github':
|
||||
return [
|
||||
'api_url' => 'https://api.github.com',
|
||||
'base_url' => 'https://github.com',
|
||||
'site_info' => [
|
||||
'name' => 'GitHub',
|
||||
'url' => 'https://github.com',
|
||||
'favicon' => 'https://github.com/favicon.ico',
|
||||
'color' => '#24292f'
|
||||
]
|
||||
];
|
||||
|
||||
case 'gitea':
|
||||
if (empty($custom_domain)) {
|
||||
return null;
|
||||
}
|
||||
$domain = $this->normalize_domain($custom_domain);
|
||||
$site_name = $custom_site_name ?: $this->get_site_name($domain, 'Gitea');
|
||||
return [
|
||||
'api_url' => "https://{$domain}/api/v1",
|
||||
'base_url' => "https://{$domain}",
|
||||
'site_info' => [
|
||||
'name' => $site_name,
|
||||
'url' => "https://{$domain}",
|
||||
'favicon' => "https://{$domain}/assets/img/favicon.png",
|
||||
'color' => '#609926'
|
||||
]
|
||||
];
|
||||
|
||||
case 'forgejo':
|
||||
if (empty($custom_domain)) {
|
||||
return null;
|
||||
}
|
||||
$domain = $this->normalize_domain($custom_domain);
|
||||
$site_name = $custom_site_name ?: $this->get_site_name($domain, 'Forgejo');
|
||||
return [
|
||||
'api_url' => "https://{$domain}/api/v1",
|
||||
'base_url' => "https://{$domain}",
|
||||
'site_info' => [
|
||||
'name' => $site_name,
|
||||
'url' => "https://{$domain}",
|
||||
'favicon' => "https://{$domain}/assets/img/favicon.png",
|
||||
'color' => '#fb923c'
|
||||
]
|
||||
];
|
||||
|
||||
case 'gitlab':
|
||||
if (empty($custom_domain)) {
|
||||
return null;
|
||||
}
|
||||
$domain = $this->normalize_domain($custom_domain);
|
||||
$site_name = $custom_site_name ?: $this->get_site_name($domain, 'GitLab');
|
||||
return [
|
||||
'api_url' => "https://{$domain}/api/v4",
|
||||
'base_url' => "https://{$domain}",
|
||||
'site_info' => [
|
||||
'name' => $site_name,
|
||||
'url' => "https://{$domain}",
|
||||
'favicon' => "https://{$domain}/assets/favicon.ico",
|
||||
'color' => '#fc6d26'
|
||||
]
|
||||
];
|
||||
|
||||
case 'custom':
|
||||
if (empty($custom_domain)) {
|
||||
return null;
|
||||
}
|
||||
$domain = $this->normalize_domain($custom_domain);
|
||||
$site_name = $custom_site_name ?: $this->get_site_name($domain, 'Git Service');
|
||||
return [
|
||||
'api_url' => "https://{$domain}/api/v1",
|
||||
'base_url' => "https://{$domain}",
|
||||
'site_info' => [
|
||||
'name' => $site_name,
|
||||
'url' => "https://{$domain}",
|
||||
'favicon' => "https://{$domain}/favicon.ico",
|
||||
'color' => '#6366f1'
|
||||
]
|
||||
];
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function get_site_name(string $domain, string $fallback): string {
|
||||
$cache_key = 'git_embed_site_name_' . md5($domain);
|
||||
$cached = get_transient($cache_key);
|
||||
|
||||
if ($cached !== false) {
|
||||
return $cached;
|
||||
}
|
||||
|
||||
$response = wp_remote_get("https://{$domain}", [
|
||||
'timeout' => 10,
|
||||
'headers' => [
|
||||
'User-Agent' => 'Git-Embed-FeiCode/1.0'
|
||||
]
|
||||
]);
|
||||
|
||||
if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
|
||||
$body = wp_remote_retrieve_body($response);
|
||||
if (preg_match('/<title[^>]*>([^<]+)<\/title>/i', $body, $matches)) {
|
||||
$title = trim(html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8'));
|
||||
if (!empty($title) && strlen($title) < 100) {
|
||||
set_transient($cache_key, $title, DAY_IN_SECONDS);
|
||||
return $title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_transient($cache_key, $fallback, HOUR_IN_SECONDS);
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
private function normalize_domain(string $domain): string {
|
||||
$domain = trim($domain);
|
||||
$domain = preg_replace('/^https?:\/\//', '', $domain);
|
||||
$domain = rtrim($domain, '/');
|
||||
return $domain;
|
||||
}
|
||||
|
||||
private function normalize_repository_data(array $data, string $platform, array $api_config): array {
|
||||
$base_url = $api_config['base_url'];
|
||||
|
||||
if ($platform === 'gitlab') {
|
||||
return [
|
||||
'name' => $data['name'],
|
||||
'full_name' => $data['path_with_namespace'] ?? ($data['namespace']['name'] . '/' . $data['name']),
|
||||
'description' => $data['description'],
|
||||
'html_url' => $data['web_url'],
|
||||
'language' => $data['language'] ?? null,
|
||||
'stargazers_count' => $data['star_count'] ?? 0,
|
||||
'forks_count' => $data['forks_count'] ?? 0,
|
||||
'open_issues_count' => $data['open_issues_count'] ?? 0,
|
||||
'clone_url' => $data['http_url_to_repo'],
|
||||
'archive_url' => $this->get_archive_url($data, $platform, $base_url),
|
||||
'owner' => [
|
||||
'login' => $data['namespace']['name'] ?? $data['owner']['username'],
|
||||
'avatar_url' => $data['namespace']['avatar_url'] ?? $data['owner']['avatar_url'],
|
||||
'html_url' => $base_url . '/' . ($data['namespace']['name'] ?? $data['owner']['username']),
|
||||
'type' => $this->normalize_owner_type($data['namespace']['kind'] ?? 'user')
|
||||
],
|
||||
'site_info' => $api_config['site_info'],
|
||||
'platform' => $platform
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $data['name'],
|
||||
'full_name' => $data['full_name'] ?? ($data['owner']['login'] . '/' . $data['name']),
|
||||
'description' => $data['description'],
|
||||
'html_url' => $data['html_url'],
|
||||
'language' => $data['language'],
|
||||
'stargazers_count' => $data['stargazers_count'] ?? $data['stars_count'] ?? 0,
|
||||
'forks_count' => $data['forks_count'] ?? $data['forks'] ?? 0,
|
||||
'open_issues_count' => $data['open_issues_count'] ?? $data['open_issues'] ?? 0,
|
||||
'clone_url' => $data['clone_url'],
|
||||
'archive_url' => $this->get_archive_url($data, $platform, $base_url),
|
||||
'owner' => [
|
||||
'login' => $data['owner']['login'],
|
||||
'avatar_url' => $data['owner']['avatar_url'],
|
||||
'html_url' => $data['owner']['html_url'] ?? $base_url . '/' . $data['owner']['login'],
|
||||
'type' => $this->normalize_owner_type($data['owner']['type'] ?? 'User')
|
||||
],
|
||||
'site_info' => $api_config['site_info'],
|
||||
'platform' => $platform
|
||||
];
|
||||
}
|
||||
|
||||
private function get_archive_url(array $data, string $platform, string $base_url): string {
|
||||
if (isset($data['archive_url'])) {
|
||||
return $data['archive_url'];
|
||||
}
|
||||
|
||||
$owner = $data['owner']['login'] ?? $data['namespace']['name'] ?? '';
|
||||
$repo = $data['name'];
|
||||
|
||||
switch ($platform) {
|
||||
case 'github':
|
||||
return "https://api.github.com/repos/{$owner}/{$repo}/zipball/{archive_format}{/ref}";
|
||||
case 'gitlab':
|
||||
$project_id = $data['id'] ?? '';
|
||||
return "{$base_url}/api/v4/projects/{$project_id}/repository/archive.zip";
|
||||
case 'gitea':
|
||||
case 'forgejo':
|
||||
case 'custom':
|
||||
return "{$base_url}/{$owner}/{$repo}/archive/main.zip";
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
private function normalize_owner_type(string $type): string {
|
||||
$type = strtolower($type);
|
||||
switch ($type) {
|
||||
case 'organization':
|
||||
case 'org':
|
||||
return 'Organization';
|
||||
case 'user':
|
||||
default:
|
||||
return 'User';
|
||||
}
|
||||
}
|
||||
|
||||
private function cache_avatar(string $avatar_url): void {
|
||||
if (empty($avatar_url)) {
|
||||
return;
|
||||
|
@ -239,30 +452,34 @@ class GitEmbedFeiCode {
|
|||
$show_view_button = $attributes['showViewButton'] ?? true;
|
||||
$show_clone_button = $attributes['showCloneButton'] ?? true;
|
||||
$show_download_button = $attributes['showDownloadButton'] ?? true;
|
||||
$show_issues_button = $attributes['showIssuesButton'] ?? false;
|
||||
$show_forks_button = $attributes['showForksButton'] ?? false;
|
||||
$show_avatar = $attributes['showAvatar'] ?? true;
|
||||
$show_site_info = $attributes['showSiteInfo'] ?? true;
|
||||
$avatar_size = $attributes['avatarSize'] ?? 'medium';
|
||||
$card_style = $attributes['cardStyle'] ?? 'default';
|
||||
$button_style = $attributes['buttonStyle'] ?? 'primary';
|
||||
$button_style = $attributes['buttonStyle'] ?? 'default';
|
||||
$button_size = $attributes['buttonSize'] ?? 'medium';
|
||||
$alignment = $attributes['alignment'] ?? 'none';
|
||||
|
||||
$align_class = $alignment !== 'none' ? " align{$alignment}" : '';
|
||||
$card_class = $card_style !== 'default' ? " git-embed-card-{$card_style}" : '';
|
||||
$avatar_class = "git-embed-avatar-{$avatar_size}";
|
||||
$button_class = "git-embed-button-{$button_size}";
|
||||
|
||||
$download_url = str_replace('{archive_format}', 'zipball', $repo_data['archive_url']);
|
||||
$download_url = str_replace('{/ref}', '/main', $download_url);
|
||||
$download_url = $this->get_download_url($repo_data);
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div class="wp-block-git-embed-feicode-repository<?php echo esc_attr($align_class); ?>">
|
||||
<div class="git-embed-card<?php echo esc_attr($card_class); ?>">
|
||||
<?php if ($show_site_info): ?>
|
||||
<div class="git-embed-site-info">
|
||||
<div class="git-embed-site-info platform-<?php echo esc_attr($repo_data['platform'] ?? 'github'); ?>">
|
||||
<img src="<?php echo esc_url($repo_data['site_info']['favicon']); ?>"
|
||||
alt="<?php echo esc_attr($repo_data['site_info']['name']); ?>"
|
||||
class="git-embed-site-favicon"
|
||||
loading="lazy">
|
||||
loading="lazy"
|
||||
onerror="this.style.display='none'">
|
||||
<span class="git-embed-site-name">
|
||||
<a href="<?php echo esc_url($repo_data['site_info']['url']); ?>"
|
||||
target="_blank" rel="noopener">
|
||||
|
@ -301,12 +518,18 @@ class GitEmbedFeiCode {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($show_language && $repo_data['language']): ?>
|
||||
<span class="git-embed-language">
|
||||
<span class="dashicons dashicons-editor-code"></span>
|
||||
<?php echo esc_html($repo_data['language']); ?>
|
||||
<div class="git-embed-meta-section">
|
||||
<?php if ($show_language && $repo_data['language']): ?>
|
||||
<span class="git-embed-language">
|
||||
<span class="dashicons dashicons-editor-code"></span>
|
||||
<?php echo esc_html($repo_data['language']); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
|
||||
<span class="git-embed-platform-badge platform-<?php echo esc_attr($repo_data['platform'] ?? 'github'); ?>">
|
||||
<?php echo esc_html(strtoupper($repo_data['platform'] ?? 'github')); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($show_description && $repo_data['description']): ?>
|
||||
|
@ -336,11 +559,11 @@ class GitEmbedFeiCode {
|
|||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($show_actions && ($show_view_button || $show_clone_button || $show_download_button)): ?>
|
||||
<?php if ($show_actions && ($show_view_button || $show_clone_button || $show_download_button || $show_issues_button || $show_forks_button)): ?>
|
||||
<div class="git-embed-actions">
|
||||
<?php if ($show_view_button): ?>
|
||||
<a href="<?php echo esc_url($repo_data['html_url']); ?>"
|
||||
class="git-embed-button git-embed-button-<?php echo esc_attr($button_style); ?>"
|
||||
class="git-embed-button git-embed-button-<?php echo esc_attr($button_style); ?> <?php echo esc_attr($button_class); ?>"
|
||||
target="_blank" rel="noopener">
|
||||
<span class="dashicons dashicons-external"></span>
|
||||
View Repository
|
||||
|
@ -349,7 +572,7 @@ class GitEmbedFeiCode {
|
|||
|
||||
<?php if ($show_clone_button): ?>
|
||||
<button type="button"
|
||||
class="git-embed-button git-embed-button-secondary git-embed-clone-btn"
|
||||
class="git-embed-button git-embed-button-secondary <?php echo esc_attr($button_class); ?> git-embed-clone-btn"
|
||||
data-clone-url="<?php echo esc_attr($repo_data['clone_url']); ?>"
|
||||
title="Click to copy clone URL">
|
||||
<span class="dashicons dashicons-admin-page"></span>
|
||||
|
@ -359,12 +582,30 @@ class GitEmbedFeiCode {
|
|||
|
||||
<?php if ($show_download_button): ?>
|
||||
<a href="<?php echo esc_url($download_url); ?>"
|
||||
class="git-embed-button git-embed-button-secondary"
|
||||
class="git-embed-button git-embed-button-secondary <?php echo esc_attr($button_class); ?>"
|
||||
download="<?php echo esc_attr($repo_data['name']); ?>.zip">
|
||||
<span class="dashicons dashicons-download"></span>
|
||||
Download ZIP
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($show_issues_button): ?>
|
||||
<a href="<?php echo esc_url($repo_data['html_url'] . '/issues'); ?>"
|
||||
class="git-embed-button git-embed-button-outline <?php echo esc_attr($button_class); ?>"
|
||||
target="_blank" rel="noopener">
|
||||
<span class="dashicons dashicons-editor-help"></span>
|
||||
Issues (<?php echo number_format_i18n($repo_data['open_issues_count']); ?>)
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($show_forks_button): ?>
|
||||
<a href="<?php echo esc_url($repo_data['html_url'] . '/forks'); ?>"
|
||||
class="git-embed-button git-embed-button-outline <?php echo esc_attr($button_class); ?>"
|
||||
target="_blank" rel="noopener">
|
||||
<span class="dashicons dashicons-networking"></span>
|
||||
Forks (<?php echo number_format_i18n($repo_data['forks_count']); ?>)
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
@ -408,10 +649,32 @@ class GitEmbedFeiCode {
|
|||
return ob_get_clean();
|
||||
}
|
||||
|
||||
private function get_download_url(array $repo_data): string {
|
||||
$platform = $repo_data['platform'] ?? 'github';
|
||||
$archive_url = $repo_data['archive_url'] ?? '';
|
||||
|
||||
switch ($platform) {
|
||||
case 'github':
|
||||
$url = str_replace('{archive_format}', 'zipball', $archive_url);
|
||||
return str_replace('{/ref}', '/main', $url);
|
||||
|
||||
case 'gitlab':
|
||||
case 'gitea':
|
||||
case 'forgejo':
|
||||
case 'custom':
|
||||
return $archive_url;
|
||||
|
||||
default:
|
||||
return $archive_url;
|
||||
}
|
||||
}
|
||||
|
||||
public function ajax_fetch_repo(): void {
|
||||
check_ajax_referer('git_embed_nonce', 'nonce');
|
||||
|
||||
$platform = sanitize_text_field($_POST['platform'] ?? '');
|
||||
$custom_domain = sanitize_text_field($_POST['customDomain'] ?? '');
|
||||
$custom_site_name = sanitize_text_field($_POST['customSiteName'] ?? '');
|
||||
$owner = sanitize_text_field($_POST['owner'] ?? '');
|
||||
$repo = sanitize_text_field($_POST['repo'] ?? '');
|
||||
|
||||
|
@ -419,7 +682,11 @@ class GitEmbedFeiCode {
|
|||
wp_send_json_error('Repository information required');
|
||||
}
|
||||
|
||||
$repo_data = $this->fetch_repository_data($platform, $owner, $repo);
|
||||
if (in_array($platform, ['gitea', 'forgejo', 'gitlab', 'custom']) && empty($custom_domain)) {
|
||||
wp_send_json_error('Custom domain required for ' . ucfirst($platform));
|
||||
}
|
||||
|
||||
$repo_data = $this->fetch_repository_data($platform, $owner, $repo, $custom_domain, $custom_site_name);
|
||||
|
||||
if (!$repo_data) {
|
||||
wp_send_json_error('Failed to fetch repository data');
|
||||
|
@ -436,6 +703,7 @@ class GitEmbedFeiCode {
|
|||
}
|
||||
|
||||
$platform = sanitize_text_field($_POST['platform'] ?? '');
|
||||
$custom_domain = sanitize_text_field($_POST['customDomain'] ?? '');
|
||||
$owner = sanitize_text_field($_POST['owner'] ?? '');
|
||||
$repo = sanitize_text_field($_POST['repo'] ?? '');
|
||||
|
||||
|
@ -443,13 +711,13 @@ class GitEmbedFeiCode {
|
|||
wp_send_json_error('Repository information required');
|
||||
}
|
||||
|
||||
$this->clear_repository_cache($platform, $owner, $repo);
|
||||
$this->clear_repository_cache($platform, $owner, $repo, $custom_domain);
|
||||
|
||||
wp_send_json_success('Cache cleared successfully');
|
||||
}
|
||||
|
||||
private function clear_repository_cache(string $platform, string $owner, string $repo): void {
|
||||
$cache_key = "git_embed_{$platform}_{$owner}_{$repo}";
|
||||
private function clear_repository_cache(string $platform, string $owner, string $repo, string $custom_domain = ''): void {
|
||||
$cache_key = "git_embed_{$platform}_{$owner}_{$repo}" . ($custom_domain ? "_{$custom_domain}" : '');
|
||||
delete_transient($cache_key);
|
||||
|
||||
global $wpdb;
|
||||
|
|
156
style.css
156
style.css
|
@ -58,6 +58,30 @@
|
|||
border: none;
|
||||
}
|
||||
|
||||
.git-embed-card-gradient {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.git-embed-card-gradient .git-embed-title a,
|
||||
.git-embed-card-gradient .git-embed-site-name a,
|
||||
.git-embed-card-gradient .git-embed-owner-link {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.git-embed-card-gradient .git-embed-description,
|
||||
.git-embed-card-gradient .git-embed-stat {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.git-embed-card-glass {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.18);
|
||||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
|
||||
}
|
||||
|
||||
.git-embed-site-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -89,6 +113,46 @@
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.git-embed-site-info.platform-github .git-embed-site-name a {
|
||||
color: #24292f;
|
||||
}
|
||||
|
||||
.git-embed-site-info.platform-github .git-embed-site-name a:hover {
|
||||
color: #0969da;
|
||||
}
|
||||
|
||||
.git-embed-site-info.platform-gitea .git-embed-site-name a {
|
||||
color: #609926;
|
||||
}
|
||||
|
||||
.git-embed-site-info.platform-gitea .git-embed-site-name a:hover {
|
||||
color: #4a7220;
|
||||
}
|
||||
|
||||
.git-embed-site-info.platform-forgejo .git-embed-site-name a {
|
||||
color: #fb923c;
|
||||
}
|
||||
|
||||
.git-embed-site-info.platform-forgejo .git-embed-site-name a:hover {
|
||||
color: #ea580c;
|
||||
}
|
||||
|
||||
.git-embed-site-info.platform-gitlab .git-embed-site-name a {
|
||||
color: #fc6d26;
|
||||
}
|
||||
|
||||
.git-embed-site-info.platform-gitlab .git-embed-site-name a:hover {
|
||||
color: #e24000;
|
||||
}
|
||||
|
||||
.git-embed-site-info.platform-custom .git-embed-site-name a {
|
||||
color: #6366f1;
|
||||
}
|
||||
|
||||
.git-embed-site-info.platform-custom .git-embed-site-name a:hover {
|
||||
color: #4f46e5;
|
||||
}
|
||||
|
||||
.git-embed-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
@ -318,6 +382,50 @@
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
.git-embed-button-ghost {
|
||||
color: #0073aa;
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.git-embed-button-ghost:hover {
|
||||
background-color: rgba(0, 115, 170, 0.1);
|
||||
border-color: #0073aa;
|
||||
color: #0073aa;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.git-embed-button-default {
|
||||
color: #24292f;
|
||||
background-color: #f6f8fa;
|
||||
border-color: #d1d5da;
|
||||
}
|
||||
|
||||
.git-embed-button-default:hover {
|
||||
background-color: #f3f4f6;
|
||||
border-color: #c7ccd1;
|
||||
color: #24292f;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.git-embed-button-small {
|
||||
padding: 4px 8px;
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.git-embed-button-medium {
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.git-embed-button-large {
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.git-embed-clone-btn:hover .dashicons {
|
||||
animation: pulse 0.3s ease-in-out;
|
||||
}
|
||||
|
@ -523,4 +631,52 @@
|
|||
|
||||
.git-embed-owner-type:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.git-embed-custom-domain-notice {
|
||||
background: #fff3cd;
|
||||
border: 1px solid #ffeaa7;
|
||||
color: #856404;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.git-embed-platform-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
padding: 2px 6px;
|
||||
border-radius: 8px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.git-embed-platform-badge.platform-github {
|
||||
background: #f6f8fa;
|
||||
color: #24292f;
|
||||
}
|
||||
|
||||
.git-embed-platform-badge.platform-gitea {
|
||||
background: #f0f9e8;
|
||||
color: #609926;
|
||||
}
|
||||
|
||||
.git-embed-platform-badge.platform-forgejo {
|
||||
background: #fef3e2;
|
||||
color: #fb923c;
|
||||
}
|
||||
|
||||
.components-panel__body .components-text-control__input:invalid {
|
||||
border-color: #d63638;
|
||||
box-shadow: 0 0 0 1px #d63638;
|
||||
}
|
||||
|
||||
.components-panel__body .components-text-control__help {
|
||||
font-size: 12px;
|
||||
color: #757575;
|
||||
margin-top: 4px;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue