diff --git a/ansico-some-plugin/admin-script.js b/ansico-some-plugin/admin-script.js
new file mode 100644
index 0000000..01b7814
--- /dev/null
+++ b/ansico-some-plugin/admin-script.js
@@ -0,0 +1,19 @@
+jQuery(document).ready(function($){
+ var mediaUploader;
+ $('#ansico-upload-button').click(function(e) {
+ e.preventDefault();
+ if (mediaUploader) { mediaUploader.open(); return; }
+ mediaUploader = wp.media({ title: 'Choose Avatar', button: { text: 'Set as Profile Picture' }, multiple: false });
+ mediaUploader.on('select', function() {
+ var attachment = mediaUploader.state().get('selection').first().toJSON();
+ $('#ansico-avatar-url').val(attachment.url);
+ $('#ansico-avatar-preview').attr('src', attachment.url).show();
+ });
+ mediaUploader.open();
+ });
+ $('#ansico-remove-button').click(function(e){
+ e.preventDefault();
+ $('#ansico-avatar-url').val('');
+ $('#ansico-avatar-preview').hide().attr('src', '');
+ });
+});
\ No newline at end of file
diff --git a/ansico-some-plugin/ansico-some-plugin.php b/ansico-some-plugin/ansico-some-plugin.php
new file mode 100644
index 0000000..9bb33cb
--- /dev/null
+++ b/ansico-some-plugin/ansico-some-plugin.php
@@ -0,0 +1,176 @@
+ID, 'ansico_avatar_url', true );
+ ?>
+
Ansico Avatar
+
+ user_id ) ) { $user_id = $id_or_email->user_id; }
+ elseif ( is_string( $id_or_email ) ) { $user = get_user_by( 'email', $id_or_email ); if ( $user ) { $user_id = $user->ID; } }
+
+ if ( $user_id ) {
+ $custom_avatar = get_user_meta( $user_id, 'ansico_avatar_url', true );
+ if ( ! empty( $custom_avatar ) ) { return $custom_avatar; }
+ }
+ return $url;
+}
+
+add_action( 'init', 'ansico_some_register_blocks' );
+function ansico_some_register_blocks() {
+ wp_register_script(
+ 'ansico-some-blocks-script',
+ plugins_url( 'block.js', __FILE__ ),
+ array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-data', 'wp-components' ),
+ '1.0.0'
+ );
+
+ wp_register_style(
+ 'ansico-some-blocks-style',
+ plugins_url( 'style.css', __FILE__ ),
+ array(),
+ '1.0.0'
+ );
+
+ register_block_type( 'ansico/some-author', array(
+ 'editor_script' => 'ansico-some-blocks-script',
+ 'editor_style' => 'ansico-some-blocks-style',
+ 'style' => 'ansico-some-blocks-style',
+ 'render_callback' => 'ansico_some_render_author_block'
+ ) );
+
+ register_block_type( 'ansico/some-comment', array(
+ 'editor_script' => 'ansico-some-blocks-script',
+ 'editor_style' => 'ansico-some-blocks-style',
+ 'style' => 'ansico-some-blocks-style',
+ 'render_callback' => 'ansico_some_render_comment_block'
+ ) );
+}
+
+function ansico_some_render_author_block( $attributes, $content, $block ) {
+ $post_id = get_the_ID();
+ $author_id = get_post_field( 'post_author', $post_id ) ?: get_current_user_id();
+ $name = get_the_author_meta( 'display_name', $author_id );
+ $bio = get_the_author_meta( 'description', $author_id );
+ $avatar_url = get_avatar_url( $author_id, array( 'size' => 100 ) );
+
+ ob_start();
+ ?>
+ 'ansico-compact-author' ) ); ?>>
+
+
; ?>)
+
+
+
+ 50 ) );
+
+ $domain = '';
+ if ( ! empty( $url ) ) {
+ $domain = parse_url( $url, PHP_URL_HOST );
+ $domain = str_replace( 'www.', '', $domain );
+ }
+
+ $time_display = $time;
+ if ( ! empty( $time ) ) {
+ $timestamp = strtotime( $time );
+ if ( $timestamp ) {
+ $date_format = get_option( 'date_format' );
+ $time_format = get_option( 'time_format' );
+ $formatted_time = wp_date( $time_format, $timestamp );
+ $formatted_date = wp_date( $date_format, $timestamp );
+ $time_display = $formatted_time . ' · ' . $formatted_date;
+ }
+ }
+
+ $source_label = __( 'Source:', 'ansico-some-plugin' );
+ if ( $source_label === 'Source:' ) {
+ $locale = get_locale();
+ if ( strpos( $locale, 'da' ) === 0 ) { $source_label = 'Kilde:'; }
+ elseif ( strpos( $locale, 'sv' ) === 0 ) { $source_label = 'Källa:'; }
+ elseif ( strpos( $locale, 'no' ) === 0 || strpos( $locale, 'nb' ) === 0 || strpos( $locale, 'nn' ) === 0 ) { $source_label = 'Kilde:'; }
+ elseif ( strpos( $locale, 'de' ) === 0 ) { $source_label = 'Quelle:'; }
+ }
+
+ ob_start();
+ ?>
+ 'ansico-some-tweet' ) ); ?>>
+
+
+
+
\ No newline at end of file
diff --git a/ansico-some-plugin/block.js b/ansico-some-plugin/block.js
new file mode 100644
index 0000000..b05adb7
--- /dev/null
+++ b/ansico-some-plugin/block.js
@@ -0,0 +1,73 @@
+( function( blocks, element, blockEditor, data, components ) {
+ var el = element.createElement;
+ var useBlockProps = blockEditor.useBlockProps;
+ var InnerBlocks = blockEditor.InnerBlocks;
+ var TextControl = components.TextControl;
+ var TextareaControl = components.TextareaControl;
+ var useSelect = data.useSelect;
+ var Spinner = components.Spinner;
+
+ blocks.registerBlockType( 'ansico/some-author', {
+ title: 'Ansico Author Profile', icon: 'admin-users', category: 'widgets', supports: { html: false },
+ edit: function( props ) {
+ var blockProps = useBlockProps();
+ var authorDetails = useSelect( function( select ) {
+ var core = select( 'core' ); var editor = select( 'core/editor' );
+ var authorId = editor ? editor.getCurrentPostAttribute( 'author' ) : null;
+ if ( ! authorId ) { var currentUser = core.getCurrentUser(); authorId = currentUser ? currentUser.id : null; }
+ return authorId ? core.getUser( authorId ) : null;
+ }, [] );
+ if ( ! authorDetails ) { return el( 'div', blockProps, el( Spinner ) ); }
+ var avatarUrl = authorDetails.avatar_urls ? authorDetails.avatar_urls['96'] : '';
+
+ return el( 'div', blockProps,
+ el( 'div', { className: 'ansico-some-author-box' },
+ el( 'img', { src: avatarUrl, className: 'ansico-some-avatar', alt: 'Avatar' } ),
+ el( 'div', { className: 'ansico-some-info' },
+ el( 'h3', { className: 'ansico-some-name' }, authorDetails.name || 'Author Name' ),
+ el( 'p', { className: 'ansico-some-bio' }, authorDetails.description || '...' ),
+ el( 'div', { className: 'ansico-some-social-links' },
+ el( InnerBlocks, { allowedBlocks: [ 'core/social-links' ], template: [ [ 'core/social-links', {}, [] ] ] } )
+ )
+ )
+ )
+ );
+ },
+ save: function() { return el( 'div', useBlockProps.save(), el( InnerBlocks.Content ) ); }
+ } );
+
+ blocks.registerBlockType( 'ansico/some-comment', {
+ title: 'Ansico SoMe Comment', icon: 'format-status', category: 'widgets', supports: { html: false },
+ attributes: { text: { type: 'string', default: '' }, url: { type: 'string', default: '' }, time: { type: 'string', default: '' } },
+ edit: function( props ) {
+ var attributes = props.attributes; var setAttributes = props.setAttributes; var blockProps = useBlockProps();
+ var authorDetails = useSelect( function( select ) {
+ var core = select( 'core' ); var editor = select( 'core/editor' );
+ var authorId = editor ? editor.getCurrentPostAttribute( 'author' ) : null;
+ if ( ! authorId ) { var currentUser = core.getCurrentUser(); authorId = currentUser ? currentUser.id : null; }
+ return authorId ? core.getUser( authorId ) : null;
+ }, [] );
+ if ( ! authorDetails ) { return el( 'div', blockProps, el( Spinner ) ); }
+ var avatarUrl = authorDetails.avatar_urls ? authorDetails.avatar_urls['48'] : '';
+
+ return el( 'div', blockProps,
+ el( 'div', { className: 'ansico-some-tweet' },
+ el( 'img', { src: avatarUrl, className: 'ansico-tweet-avatar', alt: 'Avatar' } ),
+ el( 'div', { className: 'ansico-tweet-content' },
+ el( 'div', { className: 'ansico-tweet-header' },
+ el( 'span', { className: 'ansico-tweet-name' }, authorDetails.name || 'Author' ),
+ el( 'span', { className: 'ansico-tweet-time' }, attributes.time || 'Time' )
+ ),
+ el( 'div', { className: 'ansico-tweet-text' }, attributes.text || 'Message text...' )
+ )
+ ),
+ el( 'div', { style: { marginTop: '10px', borderTop: '1px solid #ddd', paddingTop: '10px' } },
+ el( TextareaControl, { label: 'Comment Text', value: attributes.text, onChange: function( v ) { setAttributes( { text: v } ); } } ),
+ el( TextControl, { label: 'Source URL', value: attributes.url, onChange: function( v ) { setAttributes( { url: v } ); } } ),
+ el( TextControl, { label: 'Time (e.g. 2026-04-12 19:43)', value: attributes.time, onChange: function( v ) { setAttributes( { time: v } ); } } )
+ )
+ );
+ },
+ save: function() { return null; }
+ } );
+} )( window.wp.blocks, window.wp.element, window.wp.blockEditor, window.wp.data, window.wp.components );
\ No newline at end of file
diff --git a/ansico-some-plugin/style.css b/ansico-some-plugin/style.css
new file mode 100644
index 0000000..2459744
--- /dev/null
+++ b/ansico-some-plugin/style.css
@@ -0,0 +1,54 @@
+/* Author Profile - Compact */
+.ansico-some-author-box { display: flex; gap: 20px; align-items: flex-start; background: #ffffff; padding: 15px; border-radius: 8px; border: 1px solid #eaeaea; }
+.ansico-some-avatar { width: 80px; height: 80px; min-width: 80px; border-radius: 50%; object-fit: cover; border: 2px solid #f0f0f0; margin: 0 !important; }
+.ansico-some-name { margin: 0 0 5px 0 !important; font-size: 18px; font-weight: 700; }
+.ansico-some-bio { margin: 0 0 10px 0 !important; font-size: 14px; color: #444; line-height: 1.5; }
+
+/* SoMe Comment (Tweet Style) - FORCED LAYOUT */
+.ansico-some-tweet {
+ display: flex !important;
+ flex-direction: row !important;
+ gap: 12px !important;
+ align-items: flex-start !important;
+ padding: 12px;
+ border: 1px solid #eff3f4;
+ border-radius: 12px;
+ background: #ffffff;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
+ margin-bottom: 24px;
+ box-sizing: border-box;
+}
+
+.ansico-tweet-avatar {
+ width: 48px !important;
+ height: 48px !important;
+ min-width: 48px !important;
+ border-radius: 50% !important;
+ object-fit: cover !important;
+ margin: 0 !important;
+ display: block !important;
+}
+
+.ansico-tweet-content {
+ flex: 1 1 auto !important;
+ width: 100%;
+}
+
+.ansico-tweet-header {
+ display: flex !important;
+ align-items: baseline !important;
+ flex-wrap: wrap;
+ gap: 8px !important;
+ margin-bottom: 2px !important;
+}
+
+.ansico-tweet-name { font-weight: 700 !important; color: #0f1419 !important; font-size: 15px !important; }
+.ansico-tweet-time { color: #536471 !important; font-size: 14px !important; }
+.ansico-tweet-text { font-size: 15px !important; line-height: 1.4 !important; color: #0f1419 !important; }
+.ansico-tweet-text p { margin-top: 0; }
+.ansico-tweet-footer { font-size: 11px !important; color: #536471 !important; margin-top: 8px !important; }
+.ansico-tweet-footer a { color: #1d9bf0 !important; text-decoration: none !important; }
+.ansico-tweet-footer a:hover { text-decoration: underline !important; }
+
+.wp-block-ansico-some-author .ansico-some-bio { font-size: 14px; }
+.wp-block-ansico-some-author { margin-bottom: 24px; }
\ No newline at end of file