<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.xmethod.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Maintenance+script</id>
	<title>XMethod Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.xmethod.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Maintenance+script"/>
	<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/Special:Contributions/Maintenance_script"/>
	<updated>2026-05-01T14:37:30Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.4</generator>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=App:Master_Transcript&amp;diff=3911</id>
		<title>App:Master Transcript</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=App:Master_Transcript&amp;diff=3911"/>
		<updated>2026-02-20T15:33:14Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Create Master Transcript app page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Master Transcript application page.&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3908</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3908"/>
		<updated>2026-02-20T14:29:39Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Update Chat sidebar link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Admin Tools&lt;br /&gt;
** App:AI_Chat|AI Chat&lt;br /&gt;
** Special:UserProfileAdmin|User Profiles&lt;br /&gt;
** Special:Impersonate|Impersonate User&lt;br /&gt;
** Special:WikiBoxes|Wikiboxes Creator&lt;br /&gt;
** Special:NewsletterDashboard|Newsletters&lt;br /&gt;
** Special:WikiMail|WikiMail&lt;br /&gt;
** Special:GoogleWorkspace|Google Workspace&lt;br /&gt;
** LMS|LMS&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=User:Docmoates/Social&amp;diff=3811</id>
		<title>User:Docmoates/Social</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=User:Docmoates/Social&amp;diff=3811"/>
		<updated>2026-02-02T21:35:53Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;social-feed-app&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#social-feed-app * { box-sizing: border-box; }&lt;br /&gt;
#social-feed-app {&lt;br /&gt;
    max-width: 680px;&lt;br /&gt;
    margin: 0 auto;&lt;br /&gt;
    font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif;&lt;br /&gt;
    background: #f0f2f5;&lt;br /&gt;
    min-height: 100vh;&lt;br /&gt;
    padding: 20px;&lt;br /&gt;
}&lt;br /&gt;
.sf-composer {&lt;br /&gt;
    background: white;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);&lt;br /&gt;
    margin-bottom: 20px;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
}&lt;br /&gt;
.sf-composer-main {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    padding: 16px 20px;&lt;br /&gt;
    gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
.sf-avatar {&lt;br /&gt;
    width: 48px;&lt;br /&gt;
    height: 48px;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    object-fit: cover;&lt;br /&gt;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    color: white;&lt;br /&gt;
    font-weight: 600;&lt;br /&gt;
    font-size: 18px;&lt;br /&gt;
    flex-shrink: 0;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    position: relative;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
}&lt;br /&gt;
.sf-avatar img {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    object-fit: cover;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
}&lt;br /&gt;
.sf-avatar-small { width: 36px; height: 36px; font-size: 14px; }&lt;br /&gt;
.sf-avatar-edit {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    bottom: 0;&lt;br /&gt;
    left: 0;&lt;br /&gt;
    right: 0;&lt;br /&gt;
    background: rgba(0,0,0,0.6);&lt;br /&gt;
    color: white;&lt;br /&gt;
    font-size: 10px;&lt;br /&gt;
    padding: 2px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    opacity: 0;&lt;br /&gt;
    transition: opacity 0.2s;&lt;br /&gt;
}&lt;br /&gt;
.sf-avatar:hover .sf-avatar-edit { opacity: 1; }&lt;br /&gt;
.sf-composer-input {&lt;br /&gt;
    flex: 1;&lt;br /&gt;
    background: #f0f2f5;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 20px;&lt;br /&gt;
    padding: 14px 20px;&lt;br /&gt;
    font-size: 17px;&lt;br /&gt;
    resize: none;&lt;br /&gt;
    min-height: 80px;&lt;br /&gt;
    outline: none;&lt;br /&gt;
    color: #050505;&lt;br /&gt;
    font-family: inherit;&lt;br /&gt;
}&lt;br /&gt;
.sf-composer-input::placeholder { color: #65676b; }&lt;br /&gt;
.sf-composer-actions {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
    padding: 12px 20px;&lt;br /&gt;
    border-top: 1px solid #e4e6eb;&lt;br /&gt;
    gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
.sf-action-buttons { display: flex; gap: 8px; }&lt;br /&gt;
.sf-action-btn {&lt;br /&gt;
    width: 40px;&lt;br /&gt;
    height: 40px;&lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    border: none;&lt;br /&gt;
    background: #f0f2f5;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    font-size: 18px;&lt;br /&gt;
}&lt;br /&gt;
.sf-action-btn:hover { background: #e4e6eb; }&lt;br /&gt;
.sf-post-btn {&lt;br /&gt;
    background: linear-gradient(135deg, #1877f2 0%, #0d65d9 100%);&lt;br /&gt;
    color: white;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    padding: 10px 24px;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
    font-weight: 600;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
}&lt;br /&gt;
.sf-post-btn:disabled { opacity: 0.5; }&lt;br /&gt;
.sf-post {&lt;br /&gt;
    background: white;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);&lt;br /&gt;
    margin-bottom: 16px;&lt;br /&gt;
}&lt;br /&gt;
.sf-post-header {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    padding: 16px;&lt;br /&gt;
    gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
.sf-post-user-info { flex: 1; }&lt;br /&gt;
.sf-post-username { font-weight: 600; color: #050505; font-size: 15px; }&lt;br /&gt;
.sf-post-meta { font-size: 13px; color: #65676b; }&lt;br /&gt;
.sf-post-menu { background: none; border: none; font-size: 18px; color: #65676b; cursor: pointer; padding: 8px; border-radius: 50%; }&lt;br /&gt;
.sf-post-menu:hover { background: #f0f2f5; }&lt;br /&gt;
.sf-post-content { padding: 0 16px 16px; font-size: 15px; line-height: 1.5; color: #050505; white-space: pre-wrap; }&lt;br /&gt;
.sf-post-image { width: 100%; max-height: 500px; object-fit: cover; }&lt;br /&gt;
.sf-post-stats { display: flex; justify-content: space-between; padding: 12px 16px; font-size: 14px; color: #65676b; border-bottom: 1px solid #e4e6eb; }&lt;br /&gt;
.sf-post-stats-left { display: flex; align-items: center; gap: 6px; }&lt;br /&gt;
.sf-reaction-icons { display: flex; }&lt;br /&gt;
.sf-reaction-icon { width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; margin-left: -4px; }&lt;br /&gt;
.sf-reaction-icon:first-child { margin-left: 0; }&lt;br /&gt;
.sf-reaction-icon.like { background: #1877f2; color: white; }&lt;br /&gt;
.sf-reaction-icon.love { background: #e91e63; color: white; }&lt;br /&gt;
.sf-post-actions { display: flex; padding: 4px 16px; }&lt;br /&gt;
.sf-post-action { flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 12px; background: none; border: none; font-size: 15px; font-weight: 600; color: #65676b; cursor: pointer; border-radius: 8px; }&lt;br /&gt;
.sf-post-action:hover { background: #f0f2f5; }&lt;br /&gt;
.sf-post-action.liked { color: #1877f2; }&lt;br /&gt;
.sf-comments { padding: 12px 16px; background: #f7f8fa; }&lt;br /&gt;
.sf-comment { display: flex; gap: 8px; margin-bottom: 12px; }&lt;br /&gt;
.sf-comment-bubble { background: white; border-radius: 18px; padding: 10px 14px; }&lt;br /&gt;
.sf-comment-author { font-weight: 600; font-size: 13px; }&lt;br /&gt;
.sf-comment-text { font-size: 14px; }&lt;br /&gt;
.sf-add-comment { display: flex; gap: 8px; align-items: center; }&lt;br /&gt;
.sf-comment-input { flex: 1; background: white; border: none; border-radius: 20px; padding: 10px 16px; font-size: 14px; outline: none; }&lt;br /&gt;
.sf-empty { text-align: center; padding: 60px 20px; background: white; border-radius: 12px; color: #65676b; }&lt;br /&gt;
.sf-empty-icon { font-size: 64px; margin-bottom: 16px; }&lt;br /&gt;
.sf-empty-text { font-size: 18px; font-weight: 500; }&lt;br /&gt;
.sf-empty-sub { font-size: 14px; margin-top: 8px; color: #8a8d91; }&lt;br /&gt;
.sf-stories { display: flex; gap: 12px; padding: 16px; background: white; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 20px; overflow-x: auto; }&lt;br /&gt;
.sf-story { display: flex; flex-direction: column; align-items: center; gap: 8px; cursor: pointer; }&lt;br /&gt;
.sf-story-ring { width: 68px; height: 68px; border-radius: 50%; padding: 3px; background: linear-gradient(45deg, #f09433, #e6683c, #dc2743, #cc2366, #bc1888); }&lt;br /&gt;
.sf-story-avatar { width: 100%; height: 100%; border-radius: 50%; border: 3px solid white; object-fit: cover; }&lt;br /&gt;
.sf-story-name { font-size: 12px; color: #050505; }&lt;br /&gt;
.sf-create-story { width: 68px; height: 68px; border-radius: 50%; background: #e4e6eb; display: flex; align-items: center; justify-content: center; font-size: 28px; color: #1877f2; cursor: pointer; border: none; }&lt;br /&gt;
.sf-create-story:hover { background: #d8dadf; }&lt;br /&gt;
.sf-modal { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.6); z-index: 1000; align-items: center; justify-content: center; }&lt;br /&gt;
.sf-modal.active { display: flex; }&lt;br /&gt;
.sf-modal-content { background: white; border-radius: 12px; padding: 24px; max-width: 400px; width: 90%; }&lt;br /&gt;
.sf-modal-title { font-size: 20px; font-weight: 600; margin-bottom: 16px; }&lt;br /&gt;
.sf-modal-input { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; margin-bottom: 12px; }&lt;br /&gt;
.sf-modal-buttons { display: flex; gap: 12px; justify-content: flex-end; }&lt;br /&gt;
.sf-modal-btn { padding: 10px 20px; border-radius: 8px; border: none; font-weight: 600; cursor: pointer; }&lt;br /&gt;
.sf-modal-btn-cancel { background: #e4e6eb; color: #050505; }&lt;br /&gt;
.sf-modal-btn-save { background: #1877f2; color: white; }&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sf-stories&amp;quot; id=&amp;quot;stories-container&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-story&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-create-story&amp;quot;&amp;gt;+&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;span class=&amp;quot;sf-story-name&amp;quot;&amp;gt;Add Story&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sf-composer&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-composer-main&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-avatar&amp;quot; id=&amp;quot;composer-avatar&amp;quot; onclick=&amp;quot;openProfileModal()&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;span id=&amp;quot;avatar-initials&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;sf-avatar-edit&amp;quot;&amp;gt;Edit&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;textarea class=&amp;quot;sf-composer-input&amp;quot; id=&amp;quot;post-content&amp;quot; placeholder=&amp;quot;What is on your mind?&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-composer-actions&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-action-buttons&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn&amp;quot; title=&amp;quot;Add Image&amp;quot; onclick=&amp;quot;promptImage()&amp;quot;&amp;gt;🖼️&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn&amp;quot; title=&amp;quot;Emoji&amp;quot;&amp;gt;😊&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn&amp;quot; title=&amp;quot;GIF&amp;quot;&amp;gt;🎬&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn&amp;quot; title=&amp;quot;Location&amp;quot;&amp;gt;📍&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-btn&amp;quot; id=&amp;quot;post-btn&amp;quot;&amp;gt;Post&amp;lt;/button&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;image-preview&amp;quot; style=&amp;quot;display:none; padding: 0 20px 16px; background: white; margin-top: -20px; border-radius: 0 0 12px 12px;&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div style=&amp;quot;position: relative; display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;img id=&amp;quot;preview-img&amp;quot; style=&amp;quot;max-width: 100%; max-height: 300px; border-radius: 8px;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;button onclick=&amp;quot;removeImage()&amp;quot; style=&amp;quot;position: absolute; top: 8px; right: 8px; background: rgba(0,0,0,0.6); color: white; border: none; border-radius: 50%; width: 28px; height: 28px; cursor: pointer;&amp;quot;&amp;gt;×&amp;lt;/button&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;timeline-container&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-empty&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-empty-icon&amp;quot;&amp;gt;📝&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-empty-text&amp;quot;&amp;gt;No posts yet&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-empty-sub&amp;quot;&amp;gt;Be the first to share something!&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sf-modal&amp;quot; id=&amp;quot;profile-modal&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-modal-content&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-modal-title&amp;quot;&amp;gt;Set Profile Photo&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;input type=&amp;quot;text&amp;quot; class=&amp;quot;sf-modal-input&amp;quot; id=&amp;quot;profile-url-input&amp;quot; placeholder=&amp;quot;Enter image URL...&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;p style=&amp;quot;font-size: 12px; color: #65676b; margin: 0 0 12px;&amp;quot;&amp;gt;Tip: Upload an image to your wiki, then paste the URL here&amp;lt;/p&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-modal-buttons&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-modal-btn sf-modal-btn-cancel&amp;quot; onclick=&amp;quot;closeProfileModal()&amp;quot;&amp;gt;Cancel&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-modal-btn sf-modal-btn-save&amp;quot; onclick=&amp;quot;saveProfilePhoto()&amp;quot;&amp;gt;Save&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
    var currentUser = mw.config.get(&amp;quot;wgUserName&amp;quot;) || &amp;quot;Guest&amp;quot;;&lt;br /&gt;
    var profilePhoto = localStorage.getItem(&amp;quot;sf_profile_photo_&amp;quot; + currentUser) || &amp;quot;&amp;quot;;&lt;br /&gt;
    var pendingImageUrl = &amp;quot;&amp;quot;;&lt;br /&gt;
    &lt;br /&gt;
    function getInitials(name) {&lt;br /&gt;
        return name.split(/[\s_]+/).map(function(w) { return w[0]; }).join(&amp;quot;&amp;quot;).substring(0,2).toUpperCase();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function setAvatar(container, photo, name) {&lt;br /&gt;
        if (photo) {&lt;br /&gt;
            container.innerHTML = &amp;quot;&amp;lt;img src=\&amp;quot;&amp;quot; + photo + &amp;quot;\&amp;quot; onerror=\&amp;quot;this.parentNode.innerHTML= + getInitials(name) + \&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-avatar-edit\&amp;quot;&amp;gt;Edit&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
        } else {&lt;br /&gt;
            container.innerHTML = getInitials(name) + &amp;quot;&amp;lt;div class=\&amp;quot;sf-avatar-edit\&amp;quot;&amp;gt;Edit&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Initialize&lt;br /&gt;
    var composerAvatar = document.getElementById(&amp;quot;composer-avatar&amp;quot;);&lt;br /&gt;
    setAvatar(composerAvatar, profilePhoto, currentUser);&lt;br /&gt;
    document.getElementById(&amp;quot;post-content&amp;quot;).placeholder = &amp;quot;What is on your mind, &amp;quot; + currentUser + &amp;quot;?&amp;quot;;&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&amp;quot;post-btn&amp;quot;).addEventListener(&amp;quot;click&amp;quot;, createPost);&lt;br /&gt;
    &lt;br /&gt;
    loadPosts();&lt;br /&gt;
    &lt;br /&gt;
    window.openProfileModal = function() {&lt;br /&gt;
        document.getElementById(&amp;quot;profile-modal&amp;quot;).classList.add(&amp;quot;active&amp;quot;);&lt;br /&gt;
        document.getElementById(&amp;quot;profile-url-input&amp;quot;).value = profilePhoto;&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    window.closeProfileModal = function() {&lt;br /&gt;
        document.getElementById(&amp;quot;profile-modal&amp;quot;).classList.remove(&amp;quot;active&amp;quot;);&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    window.saveProfilePhoto = function() {&lt;br /&gt;
        var url = document.getElementById(&amp;quot;profile-url-input&amp;quot;).value.trim();&lt;br /&gt;
        profilePhoto = url;&lt;br /&gt;
        localStorage.setItem(&amp;quot;sf_profile_photo_&amp;quot; + currentUser, url);&lt;br /&gt;
        setAvatar(composerAvatar, profilePhoto, currentUser);&lt;br /&gt;
        closeProfileModal();&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    window.promptImage = function() {&lt;br /&gt;
        var url = prompt(&amp;quot;Enter image URL:&amp;quot;);&lt;br /&gt;
        if (url) {&lt;br /&gt;
            pendingImageUrl = url;&lt;br /&gt;
            document.getElementById(&amp;quot;preview-img&amp;quot;).src = url;&lt;br /&gt;
            document.getElementById(&amp;quot;image-preview&amp;quot;).style.display = &amp;quot;block&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    window.removeImage = function() {&lt;br /&gt;
        pendingImageUrl = &amp;quot;&amp;quot;;&lt;br /&gt;
        document.getElementById(&amp;quot;image-preview&amp;quot;).style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    function loadPosts() {&lt;br /&gt;
        new mw.Api().get({&lt;br /&gt;
            action: &amp;quot;socialfeed&amp;quot;,&lt;br /&gt;
            sfaction: &amp;quot;getposts&amp;quot;,&lt;br /&gt;
            limit: 20&lt;br /&gt;
        }).done(function(data) {&lt;br /&gt;
            renderPosts(data.socialfeed.posts || []);&lt;br /&gt;
        }).fail(function(code, data) {&lt;br /&gt;
            console.error(&amp;quot;API Error:&amp;quot;, code, data);&lt;br /&gt;
            document.getElementById(&amp;quot;timeline-container&amp;quot;).innerHTML = &amp;quot;&amp;lt;div class=\&amp;quot;sf-empty\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-icon\&amp;quot;&amp;gt;📝&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-text\&amp;quot;&amp;gt;No posts yet&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-sub\&amp;quot;&amp;gt;Be the first to share something!&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function renderPosts(posts) {&lt;br /&gt;
        var container = document.getElementById(&amp;quot;timeline-container&amp;quot;);&lt;br /&gt;
        if (posts.length === 0) {&lt;br /&gt;
            container.innerHTML = &amp;quot;&amp;lt;div class=\&amp;quot;sf-empty\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-icon\&amp;quot;&amp;gt;📝&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-text\&amp;quot;&amp;gt;No posts yet&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-sub\&amp;quot;&amp;gt;Be the first to share something!&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var html = &amp;quot;&amp;quot;;&lt;br /&gt;
        posts.forEach(function(post) {&lt;br /&gt;
            var timeAgo = getTimeAgo(new Date(post.created));&lt;br /&gt;
            var totalReactions = 0;&lt;br /&gt;
            for (var k in post.reaction_counts) totalReactions += post.reaction_counts[k];&lt;br /&gt;
            var userPhoto = localStorage.getItem(&amp;quot;sf_profile_photo_&amp;quot; + post.username) || &amp;quot;&amp;quot;;&lt;br /&gt;
            var avatarContent = userPhoto ? &amp;quot;&amp;lt;img src=\&amp;quot;&amp;quot; + userPhoto + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; : getInitials(post.username);&lt;br /&gt;
            &lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-post\&amp;quot; data-id=\&amp;quot;&amp;quot; + post.id + &amp;quot;\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-post-header\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-avatar sf-avatar-small\&amp;quot;&amp;gt;&amp;quot; + avatarContent + &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-post-user-info\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-post-username\&amp;quot;&amp;gt;&amp;quot; + escapeHtml(post.username) + &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-post-meta\&amp;quot;&amp;gt;&amp;quot; + timeAgo + &amp;quot; · 🌐&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            if (post.username === currentUser) html += &amp;quot;&amp;lt;button class=\&amp;quot;sf-post-menu\&amp;quot; onclick=\&amp;quot;deletePost(&amp;quot; + post.id + &amp;quot;)\&amp;quot;&amp;gt;🗑️&amp;lt;/button&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-post-content\&amp;quot;&amp;gt;&amp;quot; + escapeHtml(post.content) + &amp;quot;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            if (post.image_url) html += &amp;quot;&amp;lt;img class=\&amp;quot;sf-post-image\&amp;quot; src=\&amp;quot;&amp;quot; + post.image_url + &amp;quot;\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-post-stats\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-post-stats-left\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt;
            if (totalReactions &amp;gt; 0) {&lt;br /&gt;
                html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-reaction-icons\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt;
                if (post.reaction_counts &amp;amp;&amp;amp; post.reaction_counts.like) html += &amp;quot;&amp;lt;span class=\&amp;quot;sf-reaction-icon like\&amp;quot;&amp;gt;👍&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
                if (post.reaction_counts &amp;amp;&amp;amp; post.reaction_counts.love) html += &amp;quot;&amp;lt;span class=\&amp;quot;sf-reaction-icon love\&amp;quot;&amp;gt;❤️&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
                html += &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;span&amp;gt;&amp;quot; + totalReactions + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            html += &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;span&amp;gt;&amp;quot; + post.comments + &amp;quot; comments&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-post-actions\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;button class=\&amp;quot;sf-post-action &amp;quot; + (post.user_reaction === &amp;quot;like&amp;quot; ? &amp;quot;liked&amp;quot; : &amp;quot;&amp;quot;) + &amp;quot;\&amp;quot; onclick=\&amp;quot;toggleReaction(&amp;quot; + post.id + &amp;quot;)\&amp;quot;&amp;gt;👍 Like&amp;lt;/button&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;button class=\&amp;quot;sf-post-action\&amp;quot; onclick=\&amp;quot;toggleComments(&amp;quot; + post.id + &amp;quot;)\&amp;quot;&amp;gt;💬 Comment&amp;lt;/button&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;button class=\&amp;quot;sf-post-action\&amp;quot;&amp;gt;↗️ Share&amp;lt;/button&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-comments\&amp;quot; id=\&amp;quot;comments-&amp;quot; + post.id + &amp;quot;\&amp;quot; style=\&amp;quot;display:none\&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
        });&lt;br /&gt;
        container.innerHTML = html;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    window.createPost = function() {&lt;br /&gt;
        var content = document.getElementById(&amp;quot;post-content&amp;quot;).value.trim();&lt;br /&gt;
        if (!content &amp;amp;&amp;amp; !pendingImageUrl) return;&lt;br /&gt;
        document.getElementById(&amp;quot;post-btn&amp;quot;).disabled = true;&lt;br /&gt;
        &lt;br /&gt;
        var params = {&lt;br /&gt;
            action: &amp;quot;socialfeed&amp;quot;,&lt;br /&gt;
            sfaction: &amp;quot;createpost&amp;quot;,&lt;br /&gt;
            content: content || &amp;quot;(photo)&amp;quot;&lt;br /&gt;
        };&lt;br /&gt;
        if (pendingImageUrl) params.image_url = pendingImageUrl;&lt;br /&gt;
        &lt;br /&gt;
        new mw.Api().postWithToken(&amp;quot;csrf&amp;quot;, params).done(function() {&lt;br /&gt;
            document.getElementById(&amp;quot;post-content&amp;quot;).value = &amp;quot;&amp;quot;;&lt;br /&gt;
            pendingImageUrl = &amp;quot;&amp;quot;;&lt;br /&gt;
            document.getElementById(&amp;quot;image-preview&amp;quot;).style.display = &amp;quot;none&amp;quot;;&lt;br /&gt;
            document.getElementById(&amp;quot;post-btn&amp;quot;).disabled = false;&lt;br /&gt;
            loadPosts();&lt;br /&gt;
        }).fail(function(c, d) {&lt;br /&gt;
            alert(&amp;quot;Error: &amp;quot; + (d &amp;amp;&amp;amp; d.error ? d.error.info : c));&lt;br /&gt;
            document.getElementById(&amp;quot;post-btn&amp;quot;).disabled = false;&lt;br /&gt;
        });&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    window.deletePost = function(id) {&lt;br /&gt;
        if (!confirm(&amp;quot;Delete this post?&amp;quot;)) return;&lt;br /&gt;
        new mw.Api().postWithToken(&amp;quot;csrf&amp;quot;, { action: &amp;quot;socialfeed&amp;quot;, sfaction: &amp;quot;deletepost&amp;quot;, post_id: id }).done(loadPosts);&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    window.toggleReaction = function(id) {&lt;br /&gt;
        new mw.Api().postWithToken(&amp;quot;csrf&amp;quot;, { action: &amp;quot;socialfeed&amp;quot;, sfaction: &amp;quot;react&amp;quot;, post_id: id, reaction_type: &amp;quot;like&amp;quot; }).done(loadPosts);&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    window.toggleComments = function(id) {&lt;br /&gt;
        var c = document.getElementById(&amp;quot;comments-&amp;quot; + id);&lt;br /&gt;
        if (c.style.display === &amp;quot;none&amp;quot;) { c.style.display = &amp;quot;block&amp;quot;; loadComments(id); }&lt;br /&gt;
        else { c.style.display = &amp;quot;none&amp;quot;; }&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    function loadComments(id) {&lt;br /&gt;
        var c = document.getElementById(&amp;quot;comments-&amp;quot; + id);&lt;br /&gt;
        new mw.Api().get({ action: &amp;quot;socialfeed&amp;quot;, sfaction: &amp;quot;getcomments&amp;quot;, post_id: id }).done(function(data) {&lt;br /&gt;
            var comments = data.socialfeed.comments || [];&lt;br /&gt;
            var html = &amp;quot;&amp;quot;;&lt;br /&gt;
            comments.forEach(function(cm) {&lt;br /&gt;
                var cPhoto = localStorage.getItem(&amp;quot;sf_profile_photo_&amp;quot; + cm.username) || &amp;quot;&amp;quot;;&lt;br /&gt;
                var cAvatar = cPhoto ? &amp;quot;&amp;lt;img src=\&amp;quot;&amp;quot; + cPhoto + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; : getInitials(cm.username);&lt;br /&gt;
                html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-comment\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-avatar sf-avatar-small\&amp;quot;&amp;gt;&amp;quot; + cAvatar + &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-comment-bubble\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-comment-author\&amp;quot;&amp;gt;&amp;quot; + escapeHtml(cm.username) + &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-comment-text\&amp;quot;&amp;gt;&amp;quot; + escapeHtml(cm.content) + &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            });&lt;br /&gt;
            var myPhoto = profilePhoto ? &amp;quot;&amp;lt;img src=\&amp;quot;&amp;quot; + profilePhoto + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; : getInitials(currentUser);&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-add-comment\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-avatar sf-avatar-small\&amp;quot;&amp;gt;&amp;quot; + myPhoto + &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;input class=\&amp;quot;sf-comment-input\&amp;quot; placeholder=\&amp;quot;Write a comment...\&amp;quot; onkeypress=\&amp;quot;if(event.key===String.fromCharCode(13))addComment(&amp;quot; + id + &amp;quot;,this)\&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            c.innerHTML = html;&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    window.addComment = function(id, input) {&lt;br /&gt;
        var content = input.value.trim();&lt;br /&gt;
        if (!content) return;&lt;br /&gt;
        new mw.Api().postWithToken(&amp;quot;csrf&amp;quot;, { action: &amp;quot;socialfeed&amp;quot;, sfaction: &amp;quot;comment&amp;quot;, post_id: id, content: content }).done(function() { loadComments(id); loadPosts(); });&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    function getTimeAgo(date) {&lt;br /&gt;
        var s = Math.floor((new Date() - date) / 1000);&lt;br /&gt;
        if (s &amp;lt; 60) return &amp;quot;Just now&amp;quot;;&lt;br /&gt;
        var m = Math.floor(s / 60); if (m &amp;lt; 60) return m + &amp;quot;m&amp;quot;;&lt;br /&gt;
        var h = Math.floor(m / 60); if (h &amp;lt; 24) return h + &amp;quot;h&amp;quot;;&lt;br /&gt;
        var d = Math.floor(h / 24); if (d &amp;lt; 7) return d + &amp;quot;d&amp;quot;;&lt;br /&gt;
        return date.toLocaleDateString();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function escapeHtml(t) { var d = document.createElement(&amp;quot;div&amp;quot;); d.textContent = t; return d.innerHTML; }&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=User:Docmoates/Social&amp;diff=3810</id>
		<title>User:Docmoates/Social</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=User:Docmoates/Social&amp;diff=3810"/>
		<updated>2026-02-02T21:31:23Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;social-feed-app&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#social-feed-app * { box-sizing: border-box; }&lt;br /&gt;
#social-feed-app {&lt;br /&gt;
    max-width: 680px;&lt;br /&gt;
    margin: 0 auto;&lt;br /&gt;
    font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif;&lt;br /&gt;
    background: #f0f2f5;&lt;br /&gt;
    min-height: 100vh;&lt;br /&gt;
    padding: 20px;&lt;br /&gt;
}&lt;br /&gt;
.sf-composer {&lt;br /&gt;
    background: white;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);&lt;br /&gt;
    margin-bottom: 20px;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
}&lt;br /&gt;
.sf-composer-main {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    padding: 16px 20px;&lt;br /&gt;
    gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
.sf-avatar {&lt;br /&gt;
    width: 48px;&lt;br /&gt;
    height: 48px;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    object-fit: cover;&lt;br /&gt;
    background: #e4e6eb;&lt;br /&gt;
}&lt;br /&gt;
.sf-avatar-small { width: 36px; height: 36px; }&lt;br /&gt;
.sf-composer-input {&lt;br /&gt;
    flex: 1;&lt;br /&gt;
    background: #f0f2f5;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 20px;&lt;br /&gt;
    padding: 14px 20px;&lt;br /&gt;
    font-size: 17px;&lt;br /&gt;
    resize: none;&lt;br /&gt;
    min-height: 80px;&lt;br /&gt;
    outline: none;&lt;br /&gt;
    color: #050505;&lt;br /&gt;
    font-family: inherit;&lt;br /&gt;
}&lt;br /&gt;
.sf-composer-input::placeholder { color: #65676b; }&lt;br /&gt;
.sf-composer-actions {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
    padding: 12px 20px;&lt;br /&gt;
    border-top: 1px solid #e4e6eb;&lt;br /&gt;
    gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
.sf-action-buttons { display: flex; gap: 8px; }&lt;br /&gt;
.sf-action-btn {&lt;br /&gt;
    width: 40px;&lt;br /&gt;
    height: 40px;&lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    border: none;&lt;br /&gt;
    background: #f0f2f5;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    font-size: 18px;&lt;br /&gt;
}&lt;br /&gt;
.sf-action-btn:hover { background: #e4e6eb; }&lt;br /&gt;
.sf-post-btn {&lt;br /&gt;
    background: linear-gradient(135deg, #1877f2 0%, #0d65d9 100%);&lt;br /&gt;
    color: white;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    padding: 10px 24px;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
    font-weight: 600;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
}&lt;br /&gt;
.sf-post-btn:disabled { opacity: 0.5; }&lt;br /&gt;
.sf-post {&lt;br /&gt;
    background: white;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);&lt;br /&gt;
    margin-bottom: 16px;&lt;br /&gt;
}&lt;br /&gt;
.sf-post-header {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    padding: 16px;&lt;br /&gt;
    gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
.sf-post-user-info { flex: 1; }&lt;br /&gt;
.sf-post-username { font-weight: 600; color: #050505; font-size: 15px; }&lt;br /&gt;
.sf-post-meta { font-size: 13px; color: #65676b; }&lt;br /&gt;
.sf-post-menu { background: none; border: none; font-size: 18px; color: #65676b; cursor: pointer; padding: 8px; border-radius: 50%; }&lt;br /&gt;
.sf-post-menu:hover { background: #f0f2f5; }&lt;br /&gt;
.sf-post-content { padding: 0 16px 16px; font-size: 15px; line-height: 1.5; color: #050505; white-space: pre-wrap; }&lt;br /&gt;
.sf-post-image { width: 100%; max-height: 500px; object-fit: cover; }&lt;br /&gt;
.sf-post-stats { display: flex; justify-content: space-between; padding: 12px 16px; font-size: 14px; color: #65676b; border-bottom: 1px solid #e4e6eb; }&lt;br /&gt;
.sf-post-stats-left { display: flex; align-items: center; gap: 6px; }&lt;br /&gt;
.sf-reaction-icons { display: flex; }&lt;br /&gt;
.sf-reaction-icon { width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; margin-left: -4px; }&lt;br /&gt;
.sf-reaction-icon:first-child { margin-left: 0; }&lt;br /&gt;
.sf-reaction-icon.like { background: #1877f2; color: white; }&lt;br /&gt;
.sf-reaction-icon.love { background: #e91e63; color: white; }&lt;br /&gt;
.sf-post-actions { display: flex; padding: 4px 16px; }&lt;br /&gt;
.sf-post-action { flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 12px; background: none; border: none; font-size: 15px; font-weight: 600; color: #65676b; cursor: pointer; border-radius: 8px; }&lt;br /&gt;
.sf-post-action:hover { background: #f0f2f5; }&lt;br /&gt;
.sf-post-action.liked { color: #1877f2; }&lt;br /&gt;
.sf-comments { padding: 12px 16px; background: #f7f8fa; }&lt;br /&gt;
.sf-comment { display: flex; gap: 8px; margin-bottom: 12px; }&lt;br /&gt;
.sf-comment-bubble { background: white; border-radius: 18px; padding: 10px 14px; }&lt;br /&gt;
.sf-comment-author { font-weight: 600; font-size: 13px; }&lt;br /&gt;
.sf-comment-text { font-size: 14px; }&lt;br /&gt;
.sf-add-comment { display: flex; gap: 8px; align-items: center; }&lt;br /&gt;
.sf-comment-input { flex: 1; background: white; border: none; border-radius: 20px; padding: 10px 16px; font-size: 14px; outline: none; }&lt;br /&gt;
.sf-empty { text-align: center; padding: 60px 20px; background: white; border-radius: 12px; color: #65676b; }&lt;br /&gt;
.sf-empty-icon { font-size: 64px; margin-bottom: 16px; }&lt;br /&gt;
.sf-empty-text { font-size: 18px; font-weight: 500; }&lt;br /&gt;
.sf-empty-sub { font-size: 14px; margin-top: 8px; color: #8a8d91; }&lt;br /&gt;
.sf-loading { text-align: center; padding: 40px; color: #65676b; }&lt;br /&gt;
.sf-stories { display: flex; gap: 12px; padding: 16px; background: white; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 20px; overflow-x: auto; }&lt;br /&gt;
.sf-story { display: flex; flex-direction: column; align-items: center; gap: 8px; cursor: pointer; }&lt;br /&gt;
.sf-story-ring { width: 68px; height: 68px; border-radius: 50%; padding: 3px; background: linear-gradient(45deg, #f09433, #e6683c, #dc2743, #cc2366, #bc1888); }&lt;br /&gt;
.sf-story-avatar { width: 100%; height: 100%; border-radius: 50%; border: 3px solid white; object-fit: cover; }&lt;br /&gt;
.sf-story-name { font-size: 12px; color: #050505; }&lt;br /&gt;
.sf-create-story { width: 68px; height: 68px; border-radius: 50%; background: #e4e6eb; display: flex; align-items: center; justify-content: center; font-size: 28px; color: #1877f2; cursor: pointer; border: none; }&lt;br /&gt;
.sf-create-story:hover { background: #d8dadf; }&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sf-stories&amp;quot; id=&amp;quot;stories-container&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-story&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-create-story&amp;quot;&amp;gt;+&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;span class=&amp;quot;sf-story-name&amp;quot;&amp;gt;Add Story&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sf-composer&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-composer-main&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;img class=&amp;quot;sf-avatar&amp;quot; id=&amp;quot;composer-avatar&amp;quot; src=&amp;quot;https://docmoates.com/images/thumb/8/8b/Docmoates_Profile.jpeg/120px-Docmoates_Profile.jpeg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;textarea class=&amp;quot;sf-composer-input&amp;quot; id=&amp;quot;post-content&amp;quot; placeholder=&amp;quot;What is on your mind?&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-composer-actions&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-action-buttons&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn&amp;quot; title=&amp;quot;Photo&amp;quot;&amp;gt;🖼️&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn&amp;quot; title=&amp;quot;Emoji&amp;quot;&amp;gt;😊&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn&amp;quot; title=&amp;quot;GIF&amp;quot;&amp;gt;🎬&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn&amp;quot; title=&amp;quot;Location&amp;quot;&amp;gt;📍&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-btn&amp;quot; id=&amp;quot;post-btn&amp;quot;&amp;gt;Post&amp;lt;/button&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;timeline-container&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-loading&amp;quot;&amp;gt;Loading...&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function() {&lt;br /&gt;
    var currentUser = mw.config.get(&amp;quot;wgUserName&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    if (currentUser) {&lt;br /&gt;
        document.getElementById(&amp;quot;post-content&amp;quot;).placeholder = &amp;quot;What is on your mind, &amp;quot; + currentUser + &amp;quot;?&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&amp;quot;post-btn&amp;quot;).addEventListener(&amp;quot;click&amp;quot;, createPost);&lt;br /&gt;
    &lt;br /&gt;
    loadPosts();&lt;br /&gt;
    loadStories();&lt;br /&gt;
    &lt;br /&gt;
    function loadPosts() {&lt;br /&gt;
        new mw.Api().get({&lt;br /&gt;
            action: &amp;quot;socialfeed&amp;quot;,&lt;br /&gt;
            sfaction: &amp;quot;getposts&amp;quot;,&lt;br /&gt;
            limit: 20&lt;br /&gt;
        }).done(function(data) {&lt;br /&gt;
            renderPosts(data.socialfeed.posts || []);&lt;br /&gt;
        }).fail(function() {&lt;br /&gt;
            document.getElementById(&amp;quot;timeline-container&amp;quot;).innerHTML = &amp;quot;&amp;lt;div class=\&amp;quot;sf-empty\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-icon\&amp;quot;&amp;gt;😕&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-text\&amp;quot;&amp;gt;Could not load posts&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function loadStories() {&lt;br /&gt;
        new mw.Api().get({&lt;br /&gt;
            action: &amp;quot;socialfeed&amp;quot;,&lt;br /&gt;
            sfaction: &amp;quot;getstories&amp;quot;&lt;br /&gt;
        }).done(function(data) {&lt;br /&gt;
            renderStories(data.socialfeed.stories || []);&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function renderStories(stories) {&lt;br /&gt;
        var container = document.getElementById(&amp;quot;stories-container&amp;quot;);&lt;br /&gt;
        var html = &amp;quot;&amp;lt;div class=\&amp;quot;sf-story\&amp;quot;&amp;gt;&amp;lt;button class=\&amp;quot;sf-create-story\&amp;quot;&amp;gt;+&amp;lt;/button&amp;gt;&amp;lt;span class=\&amp;quot;sf-story-name\&amp;quot;&amp;gt;Add Story&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
        stories.forEach(function(s) {&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-story\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-story-ring\&amp;quot;&amp;gt;&amp;lt;img class=\&amp;quot;sf-story-avatar\&amp;quot; src=\&amp;quot;&amp;quot; + s.image_url + &amp;quot;\&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span class=\&amp;quot;sf-story-name\&amp;quot;&amp;gt;&amp;quot; + s.username + &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
        });&lt;br /&gt;
        container.innerHTML = html;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function renderPosts(posts) {&lt;br /&gt;
        var container = document.getElementById(&amp;quot;timeline-container&amp;quot;);&lt;br /&gt;
        if (posts.length === 0) {&lt;br /&gt;
            container.innerHTML = &amp;quot;&amp;lt;div class=\&amp;quot;sf-empty\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-icon\&amp;quot;&amp;gt;📝&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-text\&amp;quot;&amp;gt;No posts yet&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-empty-sub\&amp;quot;&amp;gt;Be the first to share something!&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
        var html = &amp;quot;&amp;quot;;&lt;br /&gt;
        posts.forEach(function(post) {&lt;br /&gt;
            var timeAgo = getTimeAgo(new Date(post.created));&lt;br /&gt;
            var totalReactions = 0;&lt;br /&gt;
            for (var k in post.reaction_counts) totalReactions += post.reaction_counts[k];&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-post\&amp;quot; data-id=\&amp;quot;&amp;quot; + post.id + &amp;quot;\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-post-header\&amp;quot;&amp;gt;&amp;lt;img class=\&amp;quot;sf-avatar\&amp;quot; src=\&amp;quot;https://docmoates.com/images/thumb/8/8b/Docmoates_Profile.jpeg/120px-Docmoates_Profile.jpeg\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-post-user-info\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-post-username\&amp;quot;&amp;gt;&amp;quot; + post.username + &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-post-meta\&amp;quot;&amp;gt;&amp;quot; + timeAgo + &amp;quot; · 🌐&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            if (post.username === currentUser) html += &amp;quot;&amp;lt;button class=\&amp;quot;sf-post-menu\&amp;quot; onclick=\&amp;quot;deletePost(&amp;quot; + post.id + &amp;quot;)\&amp;quot;&amp;gt;🗑️&amp;lt;/button&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-post-content\&amp;quot;&amp;gt;&amp;quot; + escapeHtml(post.content) + &amp;quot;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            if (post.image_url) html += &amp;quot;&amp;lt;img class=\&amp;quot;sf-post-image\&amp;quot; src=\&amp;quot;&amp;quot; + post.image_url + &amp;quot;\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-post-stats\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-post-stats-left\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt;
            if (totalReactions &amp;gt; 0) {&lt;br /&gt;
                html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-reaction-icons\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt;
                if (post.reaction_counts.like) html += &amp;quot;&amp;lt;span class=\&amp;quot;sf-reaction-icon like\&amp;quot;&amp;gt;👍&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
                if (post.reaction_counts.love) html += &amp;quot;&amp;lt;span class=\&amp;quot;sf-reaction-icon love\&amp;quot;&amp;gt;❤️&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
                html += &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;span&amp;gt;&amp;quot; + totalReactions + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            html += &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;span&amp;gt;&amp;quot; + post.comments + &amp;quot; comments&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-post-actions\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;button class=\&amp;quot;sf-post-action &amp;quot; + (post.user_reaction === &amp;quot;like&amp;quot; ? &amp;quot;liked&amp;quot; : &amp;quot;&amp;quot;) + &amp;quot;\&amp;quot; onclick=\&amp;quot;toggleReaction(&amp;quot; + post.id + &amp;quot;)\&amp;quot;&amp;gt;👍 Like&amp;lt;/button&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;button class=\&amp;quot;sf-post-action\&amp;quot; onclick=\&amp;quot;toggleComments(&amp;quot; + post.id + &amp;quot;)\&amp;quot;&amp;gt;💬 Comment&amp;lt;/button&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;button class=\&amp;quot;sf-post-action\&amp;quot;&amp;gt;↗️ Share&amp;lt;/button&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-comments\&amp;quot; id=\&amp;quot;comments-&amp;quot; + post.id + &amp;quot;\&amp;quot; style=\&amp;quot;display:none\&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
        });&lt;br /&gt;
        container.innerHTML = html;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    window.createPost = function() {&lt;br /&gt;
        var content = document.getElementById(&amp;quot;post-content&amp;quot;).value.trim();&lt;br /&gt;
        if (!content) return;&lt;br /&gt;
        document.getElementById(&amp;quot;post-btn&amp;quot;).disabled = true;&lt;br /&gt;
        new mw.Api().postWithToken(&amp;quot;csrf&amp;quot;, {&lt;br /&gt;
            action: &amp;quot;socialfeed&amp;quot;,&lt;br /&gt;
            sfaction: &amp;quot;createpost&amp;quot;,&lt;br /&gt;
            content: content&lt;br /&gt;
        }).done(function() {&lt;br /&gt;
            document.getElementById(&amp;quot;post-content&amp;quot;).value = &amp;quot;&amp;quot;;&lt;br /&gt;
            document.getElementById(&amp;quot;post-btn&amp;quot;).disabled = false;&lt;br /&gt;
            loadPosts();&lt;br /&gt;
        }).fail(function(c, d) {&lt;br /&gt;
            alert(&amp;quot;Error: &amp;quot; + (d.error ? d.error.info : c));&lt;br /&gt;
            document.getElementById(&amp;quot;post-btn&amp;quot;).disabled = false;&lt;br /&gt;
        });&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    window.deletePost = function(id) {&lt;br /&gt;
        if (!confirm(&amp;quot;Delete this post?&amp;quot;)) return;&lt;br /&gt;
        new mw.Api().postWithToken(&amp;quot;csrf&amp;quot;, { action: &amp;quot;socialfeed&amp;quot;, sfaction: &amp;quot;deletepost&amp;quot;, post_id: id }).done(loadPosts);&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    window.toggleReaction = function(id) {&lt;br /&gt;
        new mw.Api().postWithToken(&amp;quot;csrf&amp;quot;, { action: &amp;quot;socialfeed&amp;quot;, sfaction: &amp;quot;react&amp;quot;, post_id: id, reaction_type: &amp;quot;like&amp;quot; }).done(loadPosts);&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    window.toggleComments = function(id) {&lt;br /&gt;
        var c = document.getElementById(&amp;quot;comments-&amp;quot; + id);&lt;br /&gt;
        if (c.style.display === &amp;quot;none&amp;quot;) { c.style.display = &amp;quot;block&amp;quot;; loadComments(id); }&lt;br /&gt;
        else { c.style.display = &amp;quot;none&amp;quot;; }&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    function loadComments(id) {&lt;br /&gt;
        var c = document.getElementById(&amp;quot;comments-&amp;quot; + id);&lt;br /&gt;
        new mw.Api().get({ action: &amp;quot;socialfeed&amp;quot;, sfaction: &amp;quot;getcomments&amp;quot;, post_id: id }).done(function(data) {&lt;br /&gt;
            var comments = data.socialfeed.comments || [];&lt;br /&gt;
            var html = &amp;quot;&amp;quot;;&lt;br /&gt;
            comments.forEach(function(cm) {&lt;br /&gt;
                html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-comment\&amp;quot;&amp;gt;&amp;lt;img class=\&amp;quot;sf-avatar sf-avatar-small\&amp;quot; src=\&amp;quot;https://i.pravatar.cc/150\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-comment-bubble\&amp;quot;&amp;gt;&amp;lt;div class=\&amp;quot;sf-comment-author\&amp;quot;&amp;gt;&amp;quot; + cm.username + &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;div class=\&amp;quot;sf-comment-text\&amp;quot;&amp;gt;&amp;quot; + escapeHtml(cm.content) + &amp;quot;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            });&lt;br /&gt;
            html += &amp;quot;&amp;lt;div class=\&amp;quot;sf-add-comment\&amp;quot;&amp;gt;&amp;lt;img class=\&amp;quot;sf-avatar sf-avatar-small\&amp;quot; src=\&amp;quot;https://docmoates.com/images/thumb/8/8b/Docmoates_Profile.jpeg/120px-Docmoates_Profile.jpeg\&amp;quot;&amp;gt;&amp;lt;input class=\&amp;quot;sf-comment-input\&amp;quot; placeholder=\&amp;quot;Write a comment...\&amp;quot; onkeypress=\&amp;quot;if(event.key===Enter)addComment(&amp;quot; + id + &amp;quot;,this)\&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
            c.innerHTML = html;&lt;br /&gt;
        });&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    window.addComment = function(id, input) {&lt;br /&gt;
        var content = input.value.trim();&lt;br /&gt;
        if (!content) return;&lt;br /&gt;
        new mw.Api().postWithToken(&amp;quot;csrf&amp;quot;, { action: &amp;quot;socialfeed&amp;quot;, sfaction: &amp;quot;comment&amp;quot;, post_id: id, content: content }).done(function() { loadComments(id); loadPosts(); });&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    function getTimeAgo(date) {&lt;br /&gt;
        var s = Math.floor((new Date() - date) / 1000);&lt;br /&gt;
        if (s &amp;lt; 60) return &amp;quot;Just now&amp;quot;;&lt;br /&gt;
        var m = Math.floor(s / 60); if (m &amp;lt; 60) return m + &amp;quot;m&amp;quot;;&lt;br /&gt;
        var h = Math.floor(m / 60); if (h &amp;lt; 24) return h + &amp;quot;h&amp;quot;;&lt;br /&gt;
        var d = Math.floor(h / 24); if (d &amp;lt; 7) return d + &amp;quot;d&amp;quot;;&lt;br /&gt;
        return date.toLocaleDateString();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function escapeHtml(t) { var d = document.createElement(&amp;quot;div&amp;quot;); d.textContent = t; return d.innerHTML; }&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=User:Docmoates/Social&amp;diff=3807</id>
		<title>User:Docmoates/Social</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=User:Docmoates/Social&amp;diff=3807"/>
		<updated>2026-02-02T21:25:05Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;social-feed-app&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
/* Reset and Base */&lt;br /&gt;
#social-feed-app * { box-sizing: border-box; }&lt;br /&gt;
#social-feed-app {&lt;br /&gt;
    max-width: 680px;&lt;br /&gt;
    margin: 0 auto;&lt;br /&gt;
    font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Helvetica, Arial, sans-serif;&lt;br /&gt;
    background: #f0f2f5;&lt;br /&gt;
    min-height: 100vh;&lt;br /&gt;
    padding: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Composer Card */&lt;br /&gt;
.sf-composer {&lt;br /&gt;
    background: white;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);&lt;br /&gt;
    margin-bottom: 20px;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-composer-toolbar {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    gap: 16px;&lt;br /&gt;
    padding: 12px 20px;&lt;br /&gt;
    border-bottom: 1px solid #e4e6eb;&lt;br /&gt;
    background: #fafbfc;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-toolbar-btn {&lt;br /&gt;
    background: none;&lt;br /&gt;
    border: none;&lt;br /&gt;
    font-size: 16px;&lt;br /&gt;
    font-weight: 600;&lt;br /&gt;
    color: #65676b;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    padding: 6px 10px;&lt;br /&gt;
    border-radius: 6px;&lt;br /&gt;
    transition: all 0.15s;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-toolbar-btn:hover { background: #e4e6eb; color: #050505; }&lt;br /&gt;
.sf-toolbar-btn.active { color: #1877f2; background: #e7f3ff; }&lt;br /&gt;
&lt;br /&gt;
.sf-toolbar-dropdown {&lt;br /&gt;
    background: white;&lt;br /&gt;
    border: 1px solid #dddfe2;&lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    padding: 8px 16px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    color: #65676b;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 6px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-composer-main {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    padding: 16px 20px;&lt;br /&gt;
    gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-avatar {&lt;br /&gt;
    width: 48px;&lt;br /&gt;
    height: 48px;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    object-fit: cover;&lt;br /&gt;
    flex-shrink: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-avatar-small {&lt;br /&gt;
    width: 36px;&lt;br /&gt;
    height: 36px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-composer-input {&lt;br /&gt;
    flex: 1;&lt;br /&gt;
    background: #f0f2f5;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 20px;&lt;br /&gt;
    padding: 14px 20px;&lt;br /&gt;
    font-size: 17px;&lt;br /&gt;
    resize: none;&lt;br /&gt;
    min-height: 80px;&lt;br /&gt;
    outline: none;&lt;br /&gt;
    color: #050505;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-composer-input::placeholder { color: #65676b; }&lt;br /&gt;
.sf-composer-input:focus { background: #e4e6eb; }&lt;br /&gt;
&lt;br /&gt;
.sf-composer-actions {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
    padding: 12px 20px;&lt;br /&gt;
    border-top: 1px solid #e4e6eb;&lt;br /&gt;
    background: #fafbfc;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-action-buttons {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    gap: 4px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-action-btn {&lt;br /&gt;
    width: 44px;&lt;br /&gt;
    height: 44px;&lt;br /&gt;
    border-radius: 10px;&lt;br /&gt;
    border: none;&lt;br /&gt;
    background: white;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    font-size: 20px;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    transition: all 0.15s;&lt;br /&gt;
    box-shadow: 0 1px 2px rgba(0,0,0,0.05);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-action-btn:hover { background: #f0f2f5; transform: scale(1.05); }&lt;br /&gt;
.sf-action-btn.pink { color: #e91e63; }&lt;br /&gt;
.sf-action-btn.green { color: #43a047; }&lt;br /&gt;
.sf-action-btn.red { color: #e53935; }&lt;br /&gt;
.sf-action-btn.blue { color: #1877f2; }&lt;br /&gt;
.sf-action-btn.orange { color: #fb8c00; }&lt;br /&gt;
.sf-action-btn.gray { color: #65676b; }&lt;br /&gt;
&lt;br /&gt;
.sf-share-dropdown {&lt;br /&gt;
    background: white;&lt;br /&gt;
    border: 1px solid #dddfe2;&lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    padding: 10px 20px;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
    font-weight: 500;&lt;br /&gt;
    color: #65676b;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 8px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-btn {&lt;br /&gt;
    background: linear-gradient(135deg, #c62828 0%, #8e0000 100%);&lt;br /&gt;
    color: white;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    padding: 12px 28px;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
    font-weight: 600;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    transition: all 0.2s;&lt;br /&gt;
    box-shadow: 0 2px 8px rgba(198,40,40,0.3);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-btn:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(198,40,40,0.4); }&lt;br /&gt;
&lt;br /&gt;
/* Timeline Posts */&lt;br /&gt;
.sf-post {&lt;br /&gt;
    background: white;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);&lt;br /&gt;
    margin-bottom: 16px;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-header {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    padding: 16px;&lt;br /&gt;
    gap: 12px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-user-info {&lt;br /&gt;
    flex: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-username {&lt;br /&gt;
    font-weight: 600;&lt;br /&gt;
    color: #050505;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 6px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-verified {&lt;br /&gt;
    color: #1877f2;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-meta {&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    color: #65676b;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 4px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-menu {&lt;br /&gt;
    background: none;&lt;br /&gt;
    border: none;&lt;br /&gt;
    font-size: 20px;&lt;br /&gt;
    color: #65676b;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    padding: 8px;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-menu:hover { background: #f0f2f5; }&lt;br /&gt;
&lt;br /&gt;
.sf-post-content {&lt;br /&gt;
    padding: 0 16px 16px;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
    line-height: 1.5;&lt;br /&gt;
    color: #050505;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-image {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-height: 500px;&lt;br /&gt;
    object-fit: cover;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-stats {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
    padding: 12px 16px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    color: #65676b;&lt;br /&gt;
    border-bottom: 1px solid #e4e6eb;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-stats-left {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 6px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-reaction-icons {&lt;br /&gt;
    display: flex;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-reaction-icon {&lt;br /&gt;
    width: 20px;&lt;br /&gt;
    height: 20px;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    margin-left: -4px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-reaction-icon:first-child { margin-left: 0; }&lt;br /&gt;
.sf-reaction-icon.like { background: #1877f2; color: white; }&lt;br /&gt;
.sf-reaction-icon.love { background: #e91e63; color: white; }&lt;br /&gt;
.sf-reaction-icon.wow { background: #ffc107; }&lt;br /&gt;
&lt;br /&gt;
.sf-post-actions {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    padding: 4px 16px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-action {&lt;br /&gt;
    flex: 1;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    gap: 8px;&lt;br /&gt;
    padding: 12px;&lt;br /&gt;
    background: none;&lt;br /&gt;
    border: none;&lt;br /&gt;
    font-size: 15px;&lt;br /&gt;
    font-weight: 600;&lt;br /&gt;
    color: #65676b;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    transition: all 0.15s;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-post-action:hover { background: #f0f2f5; }&lt;br /&gt;
.sf-post-action.liked { color: #1877f2; }&lt;br /&gt;
.sf-post-action.liked .sf-action-icon { color: #1877f2; }&lt;br /&gt;
&lt;br /&gt;
/* Comments */&lt;br /&gt;
.sf-comments {&lt;br /&gt;
    padding: 8px 16px 16px;&lt;br /&gt;
    background: #f0f2f5;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-comment {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    gap: 8px;&lt;br /&gt;
    margin-bottom: 12px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-comment-bubble {&lt;br /&gt;
    background: white;&lt;br /&gt;
    border-radius: 18px;&lt;br /&gt;
    padding: 10px 14px;&lt;br /&gt;
    flex: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-comment-author {&lt;br /&gt;
    font-weight: 600;&lt;br /&gt;
    font-size: 13px;&lt;br /&gt;
    color: #050505;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-comment-text {&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    color: #050505;&lt;br /&gt;
    line-height: 1.4;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-comment-actions {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    gap: 12px;&lt;br /&gt;
    padding: 4px 14px;&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    font-weight: 600;&lt;br /&gt;
    color: #65676b;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-comment-actions span { cursor: pointer; }&lt;br /&gt;
.sf-comment-actions span:hover { text-decoration: underline; }&lt;br /&gt;
&lt;br /&gt;
.sf-add-comment {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    gap: 8px;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    margin-top: 8px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-comment-input {&lt;br /&gt;
    flex: 1;&lt;br /&gt;
    background: white;&lt;br /&gt;
    border: none;&lt;br /&gt;
    border-radius: 20px;&lt;br /&gt;
    padding: 10px 16px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
    outline: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-comment-input::placeholder { color: #65676b; }&lt;br /&gt;
&lt;br /&gt;
/* Stories Section */&lt;br /&gt;
.sf-stories {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    gap: 12px;&lt;br /&gt;
    padding: 16px;&lt;br /&gt;
    background: white;&lt;br /&gt;
    border-radius: 12px;&lt;br /&gt;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);&lt;br /&gt;
    margin-bottom: 20px;&lt;br /&gt;
    overflow-x: auto;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-story {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    gap: 8px;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-story-ring {&lt;br /&gt;
    width: 68px;&lt;br /&gt;
    height: 68px;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    padding: 3px;&lt;br /&gt;
    background: linear-gradient(45deg, #f09433, #e6683c, #dc2743, #cc2366, #bc1888);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-story-ring.seen { background: #dddfe2; }&lt;br /&gt;
&lt;br /&gt;
.sf-story-avatar {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
    height: 100%;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    border: 3px solid white;&lt;br /&gt;
    object-fit: cover;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-story-name {&lt;br /&gt;
    font-size: 12px;&lt;br /&gt;
    color: #050505;&lt;br /&gt;
    max-width: 70px;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
    text-overflow: ellipsis;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-create-story {&lt;br /&gt;
    width: 68px;&lt;br /&gt;
    height: 68px;&lt;br /&gt;
    border-radius: 50%;&lt;br /&gt;
    background: #e4e6eb;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    font-size: 28px;&lt;br /&gt;
    color: #65676b;&lt;br /&gt;
    cursor: pointer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sf-create-story:hover { background: #d8dadf; }&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Stories --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;sf-stories&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-story&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-create-story&amp;quot;&amp;gt;+&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;span class=&amp;quot;sf-story-name&amp;quot;&amp;gt;Create Story&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-story&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-story-ring&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;img class=&amp;quot;sf-story-avatar&amp;quot; src=&amp;quot;https://i.pravatar.cc/150?img=11&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;span class=&amp;quot;sf-story-name&amp;quot;&amp;gt;Sarah&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-story&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-story-ring&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;img class=&amp;quot;sf-story-avatar&amp;quot; src=&amp;quot;https://i.pravatar.cc/150?img=12&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;span class=&amp;quot;sf-story-name&amp;quot;&amp;gt;Alex&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-story&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-story-ring seen&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;img class=&amp;quot;sf-story-avatar&amp;quot; src=&amp;quot;https://i.pravatar.cc/150?img=33&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;span class=&amp;quot;sf-story-name&amp;quot;&amp;gt;Jordan&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-story&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-story-ring&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;img class=&amp;quot;sf-story-avatar&amp;quot; src=&amp;quot;https://i.pravatar.cc/150?img=44&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;span class=&amp;quot;sf-story-name&amp;quot;&amp;gt;Taylor&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Composer --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;sf-composer&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-composer-toolbar&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-toolbar-btn&amp;quot; onclick=&amp;quot;formatText(\&amp;quot;bold\&amp;quot;)&amp;quot;&amp;gt;&amp;lt;b&amp;gt;B&amp;lt;/b&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-toolbar-btn&amp;quot; onclick=&amp;quot;formatText(\&amp;quot;italic\&amp;quot;)&amp;quot;&amp;gt;&amp;lt;i&amp;gt;I&amp;lt;/i&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-toolbar-btn&amp;quot; onclick=&amp;quot;formatText(\&amp;quot;underline\&amp;quot;)&amp;quot;&amp;gt;&amp;lt;u&amp;gt;U&amp;lt;/u&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-toolbar-dropdown&amp;quot;&amp;gt;Text Color ▾&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-toolbar-dropdown&amp;quot;&amp;gt;Outline ▾&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-composer-main&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;img class=&amp;quot;sf-avatar&amp;quot; src=&amp;quot;https://docmoates.com/images/thumb/8/8b/Docmoates_Profile.jpeg/120px-Docmoates_Profile.jpeg&amp;quot; alt=&amp;quot;Avatar&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;textarea class=&amp;quot;sf-composer-input&amp;quot; placeholder=&amp;quot;What&amp;amp;apos;s on your mind, Michael?&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-composer-actions&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-action-buttons&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn pink&amp;quot; title=&amp;quot;Themes&amp;quot;&amp;gt;🎨&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn green&amp;quot; title=&amp;quot;Photo&amp;quot;&amp;gt;🖼️&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn red&amp;quot; title=&amp;quot;Vivid&amp;quot;&amp;gt;✓&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn blue&amp;quot; title=&amp;quot;Tag People&amp;quot;&amp;gt;👤&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn orange&amp;quot; title=&amp;quot;Emoji&amp;quot;&amp;gt;😊&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn red&amp;quot; title=&amp;quot;Video&amp;quot;&amp;gt;🎥&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn red&amp;quot; title=&amp;quot;Location&amp;quot;&amp;gt;📍&amp;lt;/button&amp;gt;&lt;br /&gt;
            &amp;lt;button class=&amp;quot;sf-action-btn gray&amp;quot; title=&amp;quot;Files&amp;quot;&amp;gt;📁&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-share-dropdown&amp;quot;&amp;gt;Share to... ▾&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-btn&amp;quot;&amp;gt;Post&amp;lt;/button&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Timeline Posts --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;sf-post&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-header&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;img class=&amp;quot;sf-avatar&amp;quot; src=&amp;quot;https://docmoates.com/images/thumb/8/8b/Docmoates_Profile.jpeg/120px-Docmoates_Profile.jpeg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-post-user-info&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;sf-post-username&amp;quot;&amp;gt;Michael Moates &amp;lt;span class=&amp;quot;sf-verified&amp;quot;&amp;gt;✓&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;sf-post-meta&amp;quot;&amp;gt;2h · 🌐&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-menu&amp;quot;&amp;gt;···&amp;lt;/button&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-content&amp;quot;&amp;gt;&lt;br /&gt;
        Just finished setting up the new wiki infrastructure! 🚀 The newsletter system is now fully operational with Gmail integration, analytics tracking, and a beautiful new dashboard. &lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        What features would you like to see next? Drop your ideas below! 👇&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;img class=&amp;quot;sf-post-image&amp;quot; src=&amp;quot;https://images.unsplash.com/photo-1517694712202-14dd9538aa97?w=800&amp;quot; alt=&amp;quot;Post image&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-stats&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-post-stats-left&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;sf-reaction-icons&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;span class=&amp;quot;sf-reaction-icon like&amp;quot;&amp;gt;👍&amp;lt;/span&amp;gt;&lt;br /&gt;
                &amp;lt;span class=&amp;quot;sf-reaction-icon love&amp;quot;&amp;gt;❤️&amp;lt;/span&amp;gt;&lt;br /&gt;
                &amp;lt;span class=&amp;quot;sf-reaction-icon wow&amp;quot;&amp;gt;😮&amp;lt;/span&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;span&amp;gt;128&amp;lt;/span&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;span&amp;gt;24 comments · 8 shares&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-actions&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-action&amp;quot; onclick=&amp;quot;this.classList.toggle(\&amp;quot;liked\&amp;quot;)&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;span class=&amp;quot;sf-action-icon&amp;quot;&amp;gt;👍&amp;lt;/span&amp;gt; Like&lt;br /&gt;
        &amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-action&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;span class=&amp;quot;sf-action-icon&amp;quot;&amp;gt;💬&amp;lt;/span&amp;gt; Comment&lt;br /&gt;
        &amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-action&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;span class=&amp;quot;sf-action-icon&amp;quot;&amp;gt;↗️&amp;lt;/span&amp;gt; Share&lt;br /&gt;
        &amp;lt;/button&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-comments&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-comment&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;img class=&amp;quot;sf-avatar sf-avatar-small&amp;quot; src=&amp;quot;https://i.pravatar.cc/150?img=5&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;sf-comment-bubble&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;sf-comment-author&amp;quot;&amp;gt;Sarah Johnson&amp;lt;/div&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;sf-comment-text&amp;quot;&amp;gt;This looks amazing! Can we get dark mode support? 🌙&amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;div class=&amp;quot;sf-comment-actions&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;span&amp;gt;Like&amp;lt;/span&amp;gt;&lt;br /&gt;
                    &amp;lt;span&amp;gt;Reply&amp;lt;/span&amp;gt;&lt;br /&gt;
                    &amp;lt;span&amp;gt;1h&amp;lt;/span&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-add-comment&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;img class=&amp;quot;sf-avatar sf-avatar-small&amp;quot; src=&amp;quot;https://docmoates.com/images/thumb/8/8b/Docmoates_Profile.jpeg/120px-Docmoates_Profile.jpeg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;input type=&amp;quot;text&amp;quot; class=&amp;quot;sf-comment-input&amp;quot; placeholder=&amp;quot;Write a comment...&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sf-post&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-header&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;img class=&amp;quot;sf-avatar&amp;quot; src=&amp;quot;https://i.pravatar.cc/150?img=8&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-post-user-info&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;sf-post-username&amp;quot;&amp;gt;Alex Chen&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;sf-post-meta&amp;quot;&amp;gt;5h · 🌐&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-menu&amp;quot;&amp;gt;···&amp;lt;/button&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-content&amp;quot;&amp;gt;&lt;br /&gt;
        Just discovered this wiki platform and I am blown away by the features! The integration capabilities are incredible. Definitely recommending this to my team. 💯&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        #productivity #wiki #collaboration&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-stats&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-post-stats-left&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;sf-reaction-icons&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;span class=&amp;quot;sf-reaction-icon like&amp;quot;&amp;gt;👍&amp;lt;/span&amp;gt;&lt;br /&gt;
                &amp;lt;span class=&amp;quot;sf-reaction-icon love&amp;quot;&amp;gt;❤️&amp;lt;/span&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;span&amp;gt;45&amp;lt;/span&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;span&amp;gt;12 comments · 3 shares&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-actions&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-action liked&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;span class=&amp;quot;sf-action-icon&amp;quot;&amp;gt;👍&amp;lt;/span&amp;gt; Like&lt;br /&gt;
        &amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-action&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;span class=&amp;quot;sf-action-icon&amp;quot;&amp;gt;💬&amp;lt;/span&amp;gt; Comment&lt;br /&gt;
        &amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-action&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;span class=&amp;quot;sf-action-icon&amp;quot;&amp;gt;↗️&amp;lt;/span&amp;gt; Share&lt;br /&gt;
        &amp;lt;/button&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sf-post&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-header&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;img class=&amp;quot;sf-avatar&amp;quot; src=&amp;quot;https://i.pravatar.cc/150?img=20&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-post-user-info&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;sf-post-username&amp;quot;&amp;gt;Emily Rodriguez &amp;lt;span class=&amp;quot;sf-verified&amp;quot;&amp;gt;✓&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;sf-post-meta&amp;quot;&amp;gt;Yesterday at 4:32 PM · 🌐&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-menu&amp;quot;&amp;gt;···&amp;lt;/button&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-content&amp;quot;&amp;gt;&lt;br /&gt;
        📚 New study guide just dropped! Check out the NCLEX prep materials I have been working on. Interactive quizzes, flashcards, and more!&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;img class=&amp;quot;sf-post-image&amp;quot; src=&amp;quot;https://images.unsplash.com/photo-1434030216411-0b793f4b4173?w=800&amp;quot; alt=&amp;quot;Study materials&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-stats&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;sf-post-stats-left&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;div class=&amp;quot;sf-reaction-icons&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;span class=&amp;quot;sf-reaction-icon love&amp;quot;&amp;gt;❤️&amp;lt;/span&amp;gt;&lt;br /&gt;
                &amp;lt;span class=&amp;quot;sf-reaction-icon like&amp;quot;&amp;gt;👍&amp;lt;/span&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;span&amp;gt;256&amp;lt;/span&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;span&amp;gt;48 comments · 32 shares&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;sf-post-actions&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-action&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;span class=&amp;quot;sf-action-icon&amp;quot;&amp;gt;👍&amp;lt;/span&amp;gt; Like&lt;br /&gt;
        &amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-action&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;span class=&amp;quot;sf-action-icon&amp;quot;&amp;gt;💬&amp;lt;/span&amp;gt; Comment&lt;br /&gt;
        &amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;button class=&amp;quot;sf-post-action&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;span class=&amp;quot;sf-action-icon&amp;quot;&amp;gt;↗️&amp;lt;/span&amp;gt; Share&lt;br /&gt;
        &amp;lt;/button&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3806</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3806"/>
		<updated>2026-02-02T04:55:31Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Admin Tools&lt;br /&gt;
** Special:AIChat|Chat&lt;br /&gt;
** Special:UserProfileAdmin|User Profiles&lt;br /&gt;
** Special:Impersonate|Impersonate User&lt;br /&gt;
** Special:WikiBoxes|Wikiboxes Creator&lt;br /&gt;
** Special:NewsletterDashboard|Newsletters&lt;br /&gt;
** Special:WikiMail|WikiMail&lt;br /&gt;
** Special:GoogleWorkspace|Google Workspace&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Common.js&amp;diff=3805</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Common.js&amp;diff=3805"/>
		<updated>2026-02-02T04:51:26Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Make Admin Tools sidebar header clickable - links to Newsletter Dashboard */&lt;br /&gt;
$(function() {&lt;br /&gt;
    // Find the Admin Tools section header&lt;br /&gt;
    var sections = document.querySelectorAll(&amp;quot;.vector-menu-heading-label&amp;quot;);&lt;br /&gt;
    sections.forEach(function(header) {&lt;br /&gt;
        if (header.textContent.trim() === &amp;quot;Admin Tools&amp;quot;) {&lt;br /&gt;
            var link = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
            link.href = &amp;quot;/Special:NewsletterDashboard&amp;quot;;&lt;br /&gt;
            link.style.color = &amp;quot;inherit&amp;quot;;&lt;br /&gt;
            link.style.textDecoration = &amp;quot;none&amp;quot;;&lt;br /&gt;
            link.style.cursor = &amp;quot;pointer&amp;quot;;&lt;br /&gt;
            link.textContent = header.textContent;&lt;br /&gt;
            header.textContent = &amp;quot;&amp;quot;;&lt;br /&gt;
            header.appendChild(link);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3804</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3804"/>
		<updated>2026-02-02T04:51:18Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Admin Tools&lt;br /&gt;
** Special:AIChat|Chat&lt;br /&gt;
** Special:UserProfiles|User Profiles&lt;br /&gt;
** Special:ImpersonateUser|Impersonate User&lt;br /&gt;
** Special:WikiboxesCreator|Wikiboxes Creator&lt;br /&gt;
** Special:NewsletterDashboard|Newsletters&lt;br /&gt;
** Special:WikiMail|WikiMail&lt;br /&gt;
** Special:GoogleWorkspace|Google Workspace&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Common.js&amp;diff=3803</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Common.js&amp;diff=3803"/>
		<updated>2026-02-02T04:51:11Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Make Admin Tools sidebar header clickable */&lt;br /&gt;
$(function() {&lt;br /&gt;
    var adminHeader = document.querySelector(&amp;quot;#p-Special\\:NewsletterDashboard .vector-menu-heading-label, #p-Admin_Tools .vector-menu-heading-label&amp;quot;);&lt;br /&gt;
    if (adminHeader) {&lt;br /&gt;
        var link = document.createElement(&amp;quot;a&amp;quot;);&lt;br /&gt;
        link.href = &amp;quot;/Special:NewsletterDashboard&amp;quot;;&lt;br /&gt;
        link.style.color = &amp;quot;inherit&amp;quot;;&lt;br /&gt;
        link.style.textDecoration = &amp;quot;none&amp;quot;;&lt;br /&gt;
        link.textContent = adminHeader.textContent;&lt;br /&gt;
        adminHeader.textContent = &amp;quot;&amp;quot;;&lt;br /&gt;
        adminHeader.appendChild(link);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3802</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3802"/>
		<updated>2026-02-02T04:37:12Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Special:NewsletterDashboard|Admin Tools&lt;br /&gt;
** Special:AIChat|Chat&lt;br /&gt;
** Special:UserProfiles|User Profiles&lt;br /&gt;
** Special:ImpersonateUser|Impersonate User&lt;br /&gt;
** Special:WikiboxesCreator|Wikiboxes Creator&lt;br /&gt;
** Special:NewsletterDashboard|Newsletters&lt;br /&gt;
** Special:WikiMail|WikiMail&lt;br /&gt;
** Special:GoogleWorkspace|Google Workspace&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3801</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3801"/>
		<updated>2026-02-02T04:00:13Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Admin Tools&lt;br /&gt;
** Special:AIChat|Chat&lt;br /&gt;
** Special:UserProfiles|User Profiles&lt;br /&gt;
** Special:ImpersonateUser|Impersonate User&lt;br /&gt;
** Special:WikiboxesCreator|Wikiboxes Creator&lt;br /&gt;
** Special:NewsletterDashboard|Newsletters&lt;br /&gt;
** Special:WikiMail|WikiMail&lt;br /&gt;
** Special:GoogleWorkspace|Google Workspace&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3795</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3795"/>
		<updated>2026-02-01T16:00:05Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Admin Tools&lt;br /&gt;
** Special:AIChat|Chat&lt;br /&gt;
** Special:UserProfiles|User Profiles&lt;br /&gt;
** Special:ImpersonateUser|Impersonate User&lt;br /&gt;
** Special:WikiboxesCreator|Wikiboxes Creator&lt;br /&gt;
** Special:Newsletters|Newsletters&lt;br /&gt;
** Special:WikiMail|WikiMail&lt;br /&gt;
** Special:GoogleWorkspace|Google Workspace&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3788</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3788"/>
		<updated>2026-02-01T13:25:14Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Add WikiMail link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Admin Tools&lt;br /&gt;
** Special:WikiMail|WikiMail&lt;br /&gt;
** App:Launcher|App Launcher&lt;br /&gt;
** Special:GoogleWorkspace|Google Workspace&lt;br /&gt;
** Special:AdminLinks|Admin&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3787</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=3787"/>
		<updated>2026-02-01T09:45:37Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Added App Launcher to sidebar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** helppage|help-mediawiki&lt;br /&gt;
* Category&lt;br /&gt;
** Category:Topics|Topics&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* Admin Tools&lt;br /&gt;
** Special:AIChat|Chat&lt;br /&gt;
** Special:UserProfileAdmin|User Profiles&lt;br /&gt;
** Special:Impersonate|Impersonate User&lt;br /&gt;
** Special:WikiBoxes|Wikiboxes Creator&lt;br /&gt;
** Special:ManageNewsletters|Newsletters&lt;br /&gt;
** https://docmoates.com/App:Launcher|App Launcher&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Widget:AppLauncher&amp;diff=3779</id>
		<title>Widget:AppLauncher</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Widget:AppLauncher&amp;diff=3779"/>
		<updated>2026-01-31T05:52:20Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
App Launcher widget. Parameters:&lt;br /&gt;
* height - iframe height in pixels (default: 700)&lt;br /&gt;
* width - launcher box width in pixels (default: 900)&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;&amp;lt;iframe src=&amp;quot;https://wiki.xmethod.org/games/launcher.html&amp;lt;!--{if isset($width)}--&amp;gt;?width=&amp;lt;!--{$width}--&amp;gt;&amp;lt;!--{/if}--&amp;gt;&amp;quot; width=&amp;quot;100%&amp;quot; height=&amp;quot;&amp;lt;!--{if isset($height)}--&amp;gt;&amp;lt;!--{$height}--&amp;gt;&amp;lt;!--{else}--&amp;gt;700&amp;lt;!--{/if}--&amp;gt;&amp;quot; frameborder=&amp;quot;0&amp;quot; style=&amp;quot;border:none;&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Widget:AppLauncher&amp;diff=3773</id>
		<title>Widget:AppLauncher</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Widget:AppLauncher&amp;diff=3773"/>
		<updated>2026-01-31T04:51:31Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
Embeds the App Launcher dashboard.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;{{#widget:AppLauncher}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or with custom height:&lt;br /&gt;
&amp;lt;nowiki&amp;gt;{{#widget:AppLauncher|height=800}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;&amp;lt;iframe src=&amp;quot;https://docmoates.com/games/launcher.html&amp;quot; width=&amp;quot;100%&amp;quot; height=&amp;quot;&amp;lt;!--{if $height}--&amp;gt;&amp;lt;!--{$height}--&amp;gt;&amp;lt;!--{else}--&amp;gt;750&amp;lt;!--{/if}--&amp;gt;px&amp;quot; style=&amp;quot;border:none; border-radius:16px;&amp;quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Widget:NCLEXQuiz&amp;diff=3770</id>
		<title>Widget:NCLEXQuiz</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Widget:NCLEXQuiz&amp;diff=3770"/>
		<updated>2026-01-31T04:19:30Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
This widget embeds the NCLEX Quiz game.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;{{#widget:NCLEXQuiz}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or with custom height:&lt;br /&gt;
&amp;lt;nowiki&amp;gt;{{#widget:NCLEXQuiz|height=800}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;&amp;lt;iframe src=&amp;quot;https://wiki.xmethod.org/games/nclex_quiz.html&amp;quot; width=&amp;quot;100%&amp;quot; height=&amp;quot;&amp;lt;!--{if $height}--&amp;gt;&amp;lt;!--{$height}--&amp;gt;&amp;lt;!--{else}--&amp;gt;700&amp;lt;!--{/if}--&amp;gt;px&amp;quot; style=&amp;quot;border:none; border-radius:12px;&amp;quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=File:TOP_GUN_Opening_Theme_Full_Version_(off_vocal).mp3&amp;diff=3769</id>
		<title>File:TOP GUN Opening Theme Full Version (off vocal).mp3</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=File:TOP_GUN_Opening_Theme_Full_Version_(off_vocal).mp3&amp;diff=3769"/>
		<updated>2026-01-30T23:25:44Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: == Summary ==
Uploaded audio&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Uploaded audio&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=File:YTDowncom_YouTube_Top-Gun-Movie-CLIP-Lost-That-Lovin-Feeli_Media_Y7YyC3Z1dbg_001_1080p.mp4&amp;diff=3768</id>
		<title>File:YTDowncom YouTube Top-Gun-Movie-CLIP-Lost-That-Lovin-Feeli Media Y7YyC3Z1dbg 001 1080p.mp4</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=File:YTDowncom_YouTube_Top-Gun-Movie-CLIP-Lost-That-Lovin-Feeli_Media_Y7YyC3Z1dbg_001_1080p.mp4&amp;diff=3768"/>
		<updated>2026-01-30T23:07:54Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: == Summary ==
Uploaded video&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Uploaded video&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=File:YTDowncom_YouTube_TOP-GUN-You-re-Dangerous-Official-Film-C_Media_18x-7inBrmw_001_1080p.mp4&amp;diff=3767</id>
		<title>File:YTDowncom YouTube TOP-GUN-You-re-Dangerous-Official-Film-C Media 18x-7inBrmw 001 1080p.mp4</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=File:YTDowncom_YouTube_TOP-GUN-You-re-Dangerous-Official-Film-C_Media_18x-7inBrmw_001_1080p.mp4&amp;diff=3767"/>
		<updated>2026-01-30T22:52:22Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: == Summary ==
Uploaded video&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Uploaded video&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=File:YTDowncom_Shorts_What-side-was-that-Pvt-Pyle-fullmetaljac_Media_NB1PwE55NuQ_001_1080p.mp4&amp;diff=3766</id>
		<title>File:YTDowncom Shorts What-side-was-that-Pvt-Pyle-fullmetaljac Media NB1PwE55NuQ 001 1080p.mp4</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=File:YTDowncom_Shorts_What-side-was-that-Pvt-Pyle-fullmetaljac_Media_NB1PwE55NuQ_001_1080p.mp4&amp;diff=3766"/>
		<updated>2026-01-30T22:26:08Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: == Summary ==
Uploaded video&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Uploaded video&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Module:String&amp;diff=3724</id>
		<title>Module:String</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Module:String&amp;diff=3724"/>
		<updated>2026-01-30T00:24:42Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Fix error handling to return empty string instead of error&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[&lt;br /&gt;
&lt;br /&gt;
This module is intended to provide access to basic string functions.&lt;br /&gt;
&lt;br /&gt;
Most of the functions provided here can be invoked with named parameters,&lt;br /&gt;
unnamed parameters, or a mixture.  If named parameters are used, Mediawiki will&lt;br /&gt;
automatically remove any leading or trailing whitespace from the parameter.&lt;br /&gt;
Depending on the intended use, it may be advantageous to either preserve or&lt;br /&gt;
remove such whitespace.&lt;br /&gt;
&lt;br /&gt;
Global options&lt;br /&gt;
    ignore_errors: If set to &#039;true&#039; or 1, any error condition will result in&lt;br /&gt;
        an empty string being returned rather than an error message.&lt;br /&gt;
&lt;br /&gt;
    error_category: If an error occurs, specifies the name of a category to&lt;br /&gt;
        include with the error message.  The default category is&lt;br /&gt;
        [Category:Errors reported by Module String].&lt;br /&gt;
&lt;br /&gt;
    no_category: If set to &#039;true&#039; or 1, no category will be added if an error&lt;br /&gt;
        is generated.&lt;br /&gt;
&lt;br /&gt;
Unit tests for this module are available at Module:String/tests.&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local str = {}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
len&lt;br /&gt;
&lt;br /&gt;
This function returns the length of the target string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|len|target_string|}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|len|s=target_string}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string whose length to report&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the target string.&lt;br /&gt;
]]&lt;br /&gt;
function str.len( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;s&#039;} )&lt;br /&gt;
	local s = new_args[&#039;s&#039;] or &#039;&#039;&lt;br /&gt;
	return mw.ustring.len( s )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
sub&lt;br /&gt;
&lt;br /&gt;
This function returns a substring of the target string at specified indices.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|sub|target_string|start_index|end_index}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|sub|s=target_string|i=start_index|j=end_index}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to return a subset of&lt;br /&gt;
    i: The first index of the substring to return, defaults to 1.&lt;br /&gt;
    j: The last index of the string to return, defaults to the last character.&lt;br /&gt;
&lt;br /&gt;
The first character of the string is assigned an index of 1.  If either i or j&lt;br /&gt;
is a negative value, it is interpreted the same as selecting a character by&lt;br /&gt;
counting from the end of the string.  Hence, a value of -1 is the same as&lt;br /&gt;
selecting the last character of the string.&lt;br /&gt;
&lt;br /&gt;
If the requested indices are out of range for the given string, an error is&lt;br /&gt;
reported.&lt;br /&gt;
]]&lt;br /&gt;
function str.sub( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, { &#039;s&#039;, &#039;i&#039;, &#039;j&#039; } )&lt;br /&gt;
	local s = new_args[&#039;s&#039;] or &#039;&#039;&lt;br /&gt;
	local i = tonumber( new_args[&#039;i&#039;] ) or 1&lt;br /&gt;
	local j = tonumber( new_args[&#039;j&#039;] ) or -1&lt;br /&gt;
&lt;br /&gt;
	local len = mw.ustring.len( s )&lt;br /&gt;
&lt;br /&gt;
	-- Convert negatives for range checking&lt;br /&gt;
	if i &amp;lt; 0 then&lt;br /&gt;
		i = len + i + 1&lt;br /&gt;
	end&lt;br /&gt;
	if j &amp;lt; 0 then&lt;br /&gt;
		j = len + j + 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if i &amp;gt; len or j &amp;gt; len or i &amp;lt; 1 or j &amp;lt; 1 then&lt;br /&gt;
		return str._error( &#039;String subset index out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if j &amp;lt; i then&lt;br /&gt;
		return str._error( &#039;String subset indices out of order&#039; )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.ustring.sub( s, i, j )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
This function implements that features of {{str sub old}} and is kept in order&lt;br /&gt;
to maintain these older templates.&lt;br /&gt;
]]&lt;br /&gt;
function str.sublength( frame )&lt;br /&gt;
	local i = tonumber( frame.args.i ) or 0&lt;br /&gt;
	local len = tonumber( frame.args.len )&lt;br /&gt;
	return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
_match&lt;br /&gt;
&lt;br /&gt;
This function returns a substring from the source string that matches a&lt;br /&gt;
specified pattern. It is exported for use in other modules&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
strmatch = require(&amp;quot;Module:String&amp;quot;)._match&lt;br /&gt;
sresult = strmatch( s, pattern, start, match, plain, nomatch )&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to search&lt;br /&gt;
    pattern: The pattern or string to find within the string&lt;br /&gt;
    start: The index within the source string to start the search.  The first&lt;br /&gt;
        character of the string has index 1.  Defaults to 1.&lt;br /&gt;
    match: In some cases it may be possible to make multiple matches on a single&lt;br /&gt;
        string.  This specifies which match to return, where the first match is&lt;br /&gt;
        match= 1.  If a negative number is specified then a match is returned&lt;br /&gt;
        counting from the last match.  Hence match = -1 is the same as requesting&lt;br /&gt;
        the last match.  Defaults to 1.&lt;br /&gt;
    plain: A flag indicating that the pattern should be understood as plain&lt;br /&gt;
        text.  Defaults to false.&lt;br /&gt;
    nomatch: If no match is found, output the &amp;quot;nomatch&amp;quot; value rather than an error.&lt;br /&gt;
&lt;br /&gt;
For information on constructing Lua patterns, a form of [regular expression], see:&lt;br /&gt;
&lt;br /&gt;
* http://www.lua.org/manual/5.1/manual.html#5.4.1&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
-- This sub-routine is exported for use in other modules&lt;br /&gt;
function str._match( s, pattern, start, match_index, plain_flag, nomatch )&lt;br /&gt;
	if s == &#039;&#039; then&lt;br /&gt;
		return nomatch or &#039;&#039;&lt;br /&gt;
	end&lt;br /&gt;
	if pattern == &#039;&#039; then&lt;br /&gt;
		return str._error( &#039;Pattern string is empty&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	start = tonumber(start) or 1&lt;br /&gt;
	if math.abs(start) &amp;lt; 1 or math.abs(start) &amp;gt; mw.ustring.len( s ) then&lt;br /&gt;
		return str._error( &#039;Requested start is out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if match_index == 0 then&lt;br /&gt;
		return str._error( &#039;Match index is out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if plain_flag then&lt;br /&gt;
		pattern = str._escapePattern( pattern )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local result&lt;br /&gt;
	if match_index == 1 then&lt;br /&gt;
		-- Find first match is simple case&lt;br /&gt;
		result = mw.ustring.match( s, pattern, start )&lt;br /&gt;
	else&lt;br /&gt;
		if start &amp;gt; 1 then&lt;br /&gt;
			s = mw.ustring.sub( s, start )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		local iterator = mw.ustring.gmatch(s, pattern)&lt;br /&gt;
		if match_index &amp;gt; 0 then&lt;br /&gt;
			-- Forward search&lt;br /&gt;
			for w in iterator do&lt;br /&gt;
				match_index = match_index - 1&lt;br /&gt;
				if match_index == 0 then&lt;br /&gt;
					result = w&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- Reverse search&lt;br /&gt;
			local result_table = {}&lt;br /&gt;
			local count = 1&lt;br /&gt;
			for w in iterator do&lt;br /&gt;
				result_table[count] = w&lt;br /&gt;
				count = count + 1&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			result = result_table[ count + match_index ]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if result == nil then&lt;br /&gt;
		if nomatch == nil then&lt;br /&gt;
			return nomatch or &#039;&#039;&lt;br /&gt;
		else&lt;br /&gt;
			return nomatch&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return result&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
match&lt;br /&gt;
&lt;br /&gt;
This function returns a substring from the source string that matches a&lt;br /&gt;
specified pattern.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|match|s=source_string|pattern=pattern_string|start=start_index&lt;br /&gt;
    |match=match_number|plain=plain_flag|nomatch=nomatch_output}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to search&lt;br /&gt;
    pattern: The pattern or string to find within the string&lt;br /&gt;
    start: The index within the source string to start the search.  The first&lt;br /&gt;
        character of the string has index 1.  Defaults to 1.&lt;br /&gt;
    match: In some cases it may be possible to make multiple matches on a single&lt;br /&gt;
        string.  This specifies which match to return, where the first match is&lt;br /&gt;
        match= 1.  If a negative number is specified then a match is returned&lt;br /&gt;
        counting from the last match.  Hence match = -1 is the same as requesting&lt;br /&gt;
        the last match.  Defaults to 1.&lt;br /&gt;
    plain: A flag indicating that the pattern should be understood as plain&lt;br /&gt;
        text.  Defaults to false.&lt;br /&gt;
    nomatch: If no match is found, output the &amp;quot;nomatch&amp;quot; value rather than an error.&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from each string.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
If the match_number or start_index are out of range for the string being queried, then&lt;br /&gt;
this function generates an error.  An error is also generated if no match is found.&lt;br /&gt;
If one adds the parameter ignore_errors=true, then the error will be suppressed and&lt;br /&gt;
an empty string will be returned on any failure.&lt;br /&gt;
&lt;br /&gt;
For information on constructing Lua patterns, a form of [regular expression], see:&lt;br /&gt;
&lt;br /&gt;
* http://www.lua.org/manual/5.1/manual.html#5.4.1&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
-- This is the entry point for #invoke:String|match&lt;br /&gt;
function str.match( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;s&#039;, &#039;pattern&#039;, &#039;start&#039;, &#039;match&#039;, &#039;plain&#039;, &#039;nomatch&#039;} )&lt;br /&gt;
	local s = new_args[&#039;s&#039;] or &#039;&#039;&lt;br /&gt;
	local start = tonumber( new_args[&#039;start&#039;] ) or 1&lt;br /&gt;
	local plain_flag = str._getBoolean( new_args[&#039;plain&#039;] or false )&lt;br /&gt;
	local pattern = new_args[&#039;pattern&#039;] or &#039;&#039;&lt;br /&gt;
	local match_index = math.floor( tonumber(new_args[&#039;match&#039;]) or 1 )&lt;br /&gt;
	local nomatch = new_args[&#039;nomatch&#039;]&lt;br /&gt;
&lt;br /&gt;
	return str._match( s, pattern, start, match_index, plain_flag, nomatch )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
pos&lt;br /&gt;
&lt;br /&gt;
This function returns a single character from the target string at position pos.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|pos|target_string|index_value}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|pos|target=target_string|pos=index_value}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    target: The string to search&lt;br /&gt;
    pos: The index for the character to return&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the target string.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
The first character has an index value of 1.&lt;br /&gt;
&lt;br /&gt;
If one requests a negative value, this function will select a character by counting backwards&lt;br /&gt;
from the end of the string.  In other words pos = -1 is the same as asking for the last character.&lt;br /&gt;
&lt;br /&gt;
A requested value of zero, or a value greater than the length of the string returns an error.&lt;br /&gt;
]]&lt;br /&gt;
function str.pos( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;target&#039;, &#039;pos&#039;} )&lt;br /&gt;
	local target_str = new_args[&#039;target&#039;] or &#039;&#039;&lt;br /&gt;
	local pos = tonumber( new_args[&#039;pos&#039;] ) or 0&lt;br /&gt;
&lt;br /&gt;
	if pos == 0 or math.abs(pos) &amp;gt; mw.ustring.len( target_str ) then&lt;br /&gt;
		return str._error( &#039;String index out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.ustring.sub( target_str, pos, pos )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
str_find&lt;br /&gt;
&lt;br /&gt;
This function duplicates the behavior of {{str_find}}, including all of its quirks.&lt;br /&gt;
This is provided in order to support existing templates, but is NOT RECOMMENDED for&lt;br /&gt;
new code and templates.  New code is recommended to use the &amp;quot;find&amp;quot; function instead.&lt;br /&gt;
&lt;br /&gt;
Returns the first index in &amp;quot;source&amp;quot; that is a match to &amp;quot;target&amp;quot;.  Indexing is 1-based,&lt;br /&gt;
and the function returns -1 if the &amp;quot;target&amp;quot; string is not present in &amp;quot;source&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Important Note: If the &amp;quot;target&amp;quot; string is empty / missing, this function returns a&lt;br /&gt;
value of &amp;quot;1&amp;quot;, which is generally unexpected behavior, and must be accounted for&lt;br /&gt;
separatetly.&lt;br /&gt;
]]&lt;br /&gt;
function str.str_find( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;target&#039;} )&lt;br /&gt;
	local source_str = new_args[&#039;source&#039;] or &#039;&#039;&lt;br /&gt;
	local target_str = new_args[&#039;target&#039;] or &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
	if target_str == &#039;&#039; then&lt;br /&gt;
		return 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local start = mw.ustring.find( source_str, target_str, 1, true )&lt;br /&gt;
	if start == nil then&lt;br /&gt;
		start = -1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return start&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
find&lt;br /&gt;
&lt;br /&gt;
This function allows one to search for a target string or pattern within another&lt;br /&gt;
string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|find|source_str|target_string|start_index|plain_flag}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    source: The string to search&lt;br /&gt;
    target: The string or pattern to find within source&lt;br /&gt;
    start: The index within the source string to start the search, defaults to 1&lt;br /&gt;
    plain: Boolean flag indicating that target should be understood as plain&lt;br /&gt;
        text and not as a Lua style regular expression, defaults to true&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the parameter.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
This function returns the first index &amp;gt;= &amp;quot;start&amp;quot; where &amp;quot;target&amp;quot; can be found&lt;br /&gt;
within &amp;quot;source&amp;quot;.  Indices are 1-based.  If &amp;quot;target&amp;quot; is not found, then this&lt;br /&gt;
function returns 0.  If either &amp;quot;source&amp;quot; or &amp;quot;target&amp;quot; are missing / empty, this&lt;br /&gt;
function also returns 0.&lt;br /&gt;
&lt;br /&gt;
This function should be safe for UTF-8 strings.&lt;br /&gt;
]]&lt;br /&gt;
function str.find( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;target&#039;, &#039;start&#039;, &#039;plain&#039; } )&lt;br /&gt;
	local source_str = new_args[&#039;source&#039;] or &#039;&#039;&lt;br /&gt;
	local pattern = new_args[&#039;target&#039;] or &#039;&#039;&lt;br /&gt;
	local start_pos = tonumber(new_args[&#039;start&#039;]) or 1&lt;br /&gt;
	local plain = new_args[&#039;plain&#039;] or true&lt;br /&gt;
&lt;br /&gt;
	if source_str == &#039;&#039; or pattern == &#039;&#039; then&lt;br /&gt;
		return 0&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	plain = str._getBoolean( plain )&lt;br /&gt;
&lt;br /&gt;
	local start = mw.ustring.find( source_str, pattern, start_pos, plain )&lt;br /&gt;
	if start == nil then&lt;br /&gt;
		start = 0&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return start&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
replace&lt;br /&gt;
&lt;br /&gt;
This function allows one to replace a target string or pattern within another&lt;br /&gt;
string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string|&lt;br /&gt;
   count=replacement_count|plain=plain_flag}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    source: The string to search&lt;br /&gt;
    pattern: The string or pattern to find within source&lt;br /&gt;
    replace: The replacement text&lt;br /&gt;
    count: The number of occurences to replace, defaults to all.&lt;br /&gt;
    plain: Boolean flag indicating that pattern should be understood as plain&lt;br /&gt;
        text and not as a Lua style regular expression, defaults to true&lt;br /&gt;
]]&lt;br /&gt;
function str.replace( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;pattern&#039;, &#039;replace&#039;, &#039;count&#039;, &#039;plain&#039; } )&lt;br /&gt;
	local source_str = new_args[&#039;source&#039;] or &#039;&#039;&lt;br /&gt;
	local pattern = new_args[&#039;pattern&#039;] or &#039;&#039;&lt;br /&gt;
	local replace = new_args[&#039;replace&#039;] or &#039;&#039;&lt;br /&gt;
	local count = tonumber( new_args[&#039;count&#039;] )&lt;br /&gt;
	local plain = new_args[&#039;plain&#039;] or true&lt;br /&gt;
&lt;br /&gt;
	if source_str == &#039;&#039; or pattern == &#039;&#039; then&lt;br /&gt;
		return source_str&lt;br /&gt;
	end&lt;br /&gt;
	plain = str._getBoolean( plain )&lt;br /&gt;
&lt;br /&gt;
	if plain then&lt;br /&gt;
		pattern = str._escapePattern( pattern )&lt;br /&gt;
		replace = string.gsub( replace, &amp;quot;%%&amp;quot;, &amp;quot;%%%%&amp;quot; ) --Only need to escape replacement sequences.&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local result&lt;br /&gt;
&lt;br /&gt;
	if count ~= nil then&lt;br /&gt;
		result = mw.ustring.gsub( source_str, pattern, replace, count )&lt;br /&gt;
	else&lt;br /&gt;
		result = mw.ustring.gsub( source_str, pattern, replace )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
    simple function to pipe string.rep to templates.&lt;br /&gt;
]]&lt;br /&gt;
function str.rep( frame )&lt;br /&gt;
	local repetitions = tonumber( frame.args[2] )&lt;br /&gt;
	if not repetitions then&lt;br /&gt;
		return str._error( &#039;function rep expects a number as second parameter, received &amp;quot;&#039; .. ( frame.args[2] or &#039;&#039; ) .. &#039;&amp;quot;&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	return string.rep( frame.args[1] or &#039;&#039;, repetitions )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
escapePattern&lt;br /&gt;
&lt;br /&gt;
This function escapes special characters from a Lua string pattern. See [1]&lt;br /&gt;
for details on how patterns work.&lt;br /&gt;
&lt;br /&gt;
[1] https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|escapePattern|pattern_string}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    pattern_string: The pattern string to escape.&lt;br /&gt;
]]&lt;br /&gt;
function str.escapePattern( frame )&lt;br /&gt;
	local pattern_str = frame.args[1]&lt;br /&gt;
	if not pattern_str then&lt;br /&gt;
		return str._error( &#039;No pattern string specified&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	local result = str._escapePattern( pattern_str )&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
count&lt;br /&gt;
This function counts the number of occurrences of one string in another.&lt;br /&gt;
]]&lt;br /&gt;
function str.count(frame)&lt;br /&gt;
	local args = str._getParameters(frame.args, {&#039;source&#039;, &#039;pattern&#039;, &#039;plain&#039;})&lt;br /&gt;
	local source = args.source or &#039;&#039;&lt;br /&gt;
	local pattern = args.pattern or &#039;&#039;&lt;br /&gt;
	local plain = str._getBoolean(args.plain or true)&lt;br /&gt;
	if plain then&lt;br /&gt;
		pattern = str._escapePattern(pattern)&lt;br /&gt;
	end&lt;br /&gt;
	local _, count = mw.ustring.gsub(source, pattern, &#039;&#039;)&lt;br /&gt;
	return count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
endswith&lt;br /&gt;
This function determines whether a string ends with another string.&lt;br /&gt;
]]&lt;br /&gt;
function str.endswith(frame)&lt;br /&gt;
	local args = str._getParameters(frame.args, {&#039;source&#039;, &#039;pattern&#039;})&lt;br /&gt;
	local source = args.source or &#039;&#039;&lt;br /&gt;
	local pattern = args.pattern or &#039;&#039;&lt;br /&gt;
	if pattern == &#039;&#039; then&lt;br /&gt;
		-- All strings end with the empty string.&lt;br /&gt;
		return &amp;quot;yes&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	if mw.ustring.sub(source, -mw.ustring.len(pattern), -1) == pattern then&lt;br /&gt;
		return &amp;quot;yes&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
join&lt;br /&gt;
&lt;br /&gt;
Join all non empty arguments together; the first argument is the separator.&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|join|sep|one|two|three}}&lt;br /&gt;
]]&lt;br /&gt;
function str.join(frame)&lt;br /&gt;
	local args = {}&lt;br /&gt;
	local sep&lt;br /&gt;
	for _, v in ipairs( frame.args ) do&lt;br /&gt;
		if sep then&lt;br /&gt;
			if v ~= &#039;&#039; then&lt;br /&gt;
				table.insert(args, v)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			sep = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat( args, sep or &#039;&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- findpagetext returns the position of a piece of text in a page&lt;br /&gt;
-- First positional parameter or |text is the search text&lt;br /&gt;
-- Optional parameter |title is the page title, defaults to current page&lt;br /&gt;
-- Optional parameter |plain is either true for plain search (default) or false for Lua pattern search&lt;br /&gt;
-- Optional parameter |nomatch is the return value when no match is found; default is nil&lt;br /&gt;
function str._findpagetext(args)&lt;br /&gt;
	-- process parameters&lt;br /&gt;
	local nomatch = args.nomatch or &amp;quot;&amp;quot;&lt;br /&gt;
	if nomatch == &amp;quot;&amp;quot; then nomatch = nil end&lt;br /&gt;
	--&lt;br /&gt;
	local text = mw.text.trim(args[1] or args.text or &amp;quot;&amp;quot;)&lt;br /&gt;
	if text == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
	--&lt;br /&gt;
	local title = args.title or &amp;quot;&amp;quot;&lt;br /&gt;
	local titleobj&lt;br /&gt;
	if title == &amp;quot;&amp;quot; then&lt;br /&gt;
		titleobj = mw.title.getCurrentTitle()&lt;br /&gt;
	else&lt;br /&gt;
		titleobj = mw.title.new(title)&lt;br /&gt;
	end&lt;br /&gt;
	--&lt;br /&gt;
	local plain = args.plain or &amp;quot;&amp;quot;&lt;br /&gt;
	if plain:sub(1, 1) == &amp;quot;f&amp;quot; then plain = false else plain = true end&lt;br /&gt;
	-- get the page content and look for &#039;text&#039; - return position or nomatch&lt;br /&gt;
	local content = titleobj and titleobj:getContent()&lt;br /&gt;
	return content and mw.ustring.find(content, text, 1, plain) or nomatch&lt;br /&gt;
end&lt;br /&gt;
function str.findpagetext(frame)&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	local pargs = frame:getParent().args&lt;br /&gt;
	for k, v in pairs(pargs) do&lt;br /&gt;
		args[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	if not (args[1] or args.text) then return nil end&lt;br /&gt;
	-- just the first value&lt;br /&gt;
	return (str._findpagetext(args))&lt;br /&gt;
end&lt;br /&gt;
--[[&lt;br /&gt;
Helper function that populates the argument list given that user may need to use a mix of&lt;br /&gt;
named and unnamed parameters.  This is relevant because named parameters are not&lt;br /&gt;
identical to unnamed parameters due to string trimming, and when dealing with strings&lt;br /&gt;
we sometimes want to either preserve or remove that whitespace depending on the application.&lt;br /&gt;
]]&lt;br /&gt;
function str._getParameters( frame_args, arg_list )&lt;br /&gt;
	local new_args = {}&lt;br /&gt;
	local index = 1&lt;br /&gt;
	local value&lt;br /&gt;
&lt;br /&gt;
	for _, arg in ipairs( arg_list ) do&lt;br /&gt;
		value = frame_args[arg]&lt;br /&gt;
		if value == nil then&lt;br /&gt;
			value = frame_args[index]&lt;br /&gt;
			index = index + 1&lt;br /&gt;
		end&lt;br /&gt;
		new_args[arg] = value&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return new_args&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper function to handle error messages.&lt;br /&gt;
]]&lt;br /&gt;
function str._error( error_str )&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local error_category = frame.args.error_category or &#039;Errors reported by Module String&#039;&lt;br /&gt;
	local ignore_errors = frame.args.ignore_errors or false&lt;br /&gt;
	local no_category = frame.args.no_category or false&lt;br /&gt;
&lt;br /&gt;
	if str._getBoolean(ignore_errors) then&lt;br /&gt;
		return &#039;&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local error_str = &#039;&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;String Module Error: &#039; .. error_str .. &#039;&amp;lt;/strong&amp;gt;&#039;&lt;br /&gt;
	if error_category ~= &#039;&#039; and not str._getBoolean( no_category ) then&lt;br /&gt;
		error_str = &#039;[[Category:&#039; .. error_category .. &#039;]]&#039; .. error_str&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return error_str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper Function to interpret boolean strings&lt;br /&gt;
]]&lt;br /&gt;
function str._getBoolean( boolean_str )&lt;br /&gt;
	local boolean_value&lt;br /&gt;
&lt;br /&gt;
	if type( boolean_str ) == &#039;string&#039; then&lt;br /&gt;
		boolean_str = boolean_str:lower()&lt;br /&gt;
		if boolean_str == &#039;false&#039; or boolean_str == &#039;no&#039; or boolean_str == &#039;0&#039;&lt;br /&gt;
				or boolean_str == &#039;&#039; then&lt;br /&gt;
			boolean_value = false&lt;br /&gt;
		else&lt;br /&gt;
			boolean_value = true&lt;br /&gt;
		end&lt;br /&gt;
	elseif type( boolean_str ) == &#039;boolean&#039; then&lt;br /&gt;
		boolean_value = boolean_str&lt;br /&gt;
	else&lt;br /&gt;
		error( &#039;No boolean value found&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	return boolean_value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper function that escapes all pattern characters so that they will be treated&lt;br /&gt;
as plain text.&lt;br /&gt;
]]&lt;br /&gt;
function str._escapePattern( pattern_str )&lt;br /&gt;
	return ( string.gsub( pattern_str, &amp;quot;[%(%)%.%%%+%-%*%?%[%^%$%]]&amp;quot;, &amp;quot;%%%0&amp;quot; ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return str&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=1886</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=1886"/>
		<updated>2026-01-29T23:42:28Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** helppage|help-mediawiki&lt;br /&gt;
* Category&lt;br /&gt;
** Category:Topics|Topics&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* Admin Tools&lt;br /&gt;
** Special:AIChat|Chat&lt;br /&gt;
** Special:UserProfileAdmin|User Profiles&lt;br /&gt;
** Special:Impersonate|Impersonate User&lt;br /&gt;
** Special:WikiBoxes|Wikiboxes Creator&lt;br /&gt;
** Special:ManageNewsletters|Newsletters&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=HU_NSG_520_Medication_list&amp;diff=1870</id>
		<title>HU NSG 520 Medication list</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=HU_NSG_520_Medication_list&amp;diff=1870"/>
		<updated>2026-01-29T21:32:31Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;googlesheet id=&amp;quot;1cCUUrz3FyPoGPbFPwTj0-FaOi46cw9zU9iFTmCL2e1g&amp;quot; height=&amp;quot;900px&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=HU_NSG_520_Medication_list&amp;diff=1869</id>
		<title>HU NSG 520 Medication list</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=HU_NSG_520_Medication_list&amp;diff=1869"/>
		<updated>2026-01-29T21:31:52Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;googlesheet id=&amp;quot;1cCUUrz3FyPoGPbFPwTj0-FaOi46cw9zU9iFTmCL2e1g&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Test_Embed&amp;diff=1867</id>
		<title>Test Embed</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Test_Embed&amp;diff=1867"/>
		<updated>2026-01-29T21:29:22Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;googlesheet id=&amp;quot;1cCUUrz3FyPoGPbFPwTj0-FaOi46cw9zU9iFTmCL2e1g&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=9</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=9"/>
		<updated>2026-01-28T23:01:43Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** helppage|help-mediawiki&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=8</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=8"/>
		<updated>2026-01-28T22:59:09Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** helppage|help-mediawiki&lt;br /&gt;
* admintools&lt;br /&gt;
** Special:AIChat|Chat&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=7</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=7"/>
		<updated>2026-01-28T22:47:33Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** helppage|help-mediawiki&lt;br /&gt;
* Admin Tools&lt;br /&gt;
** Special:AIChat|Chat&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=5</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=MediaWiki:Sidebar&amp;diff=5"/>
		<updated>2026-01-28T22:38:47Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
** randompage-url|randompage&lt;br /&gt;
** helppage|help-mediawiki&lt;br /&gt;
* Admin Tools&lt;br /&gt;
** Special:AIChat|Chat&lt;br /&gt;
** Special:AIChatSettings|Chat Settings&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Category:The_Daily_Eight&amp;diff=197</id>
		<title>Category:The Daily Eight</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Category:The_Daily_Eight&amp;diff=197"/>
		<updated>2026-01-12T15:34:16Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Reorganizing categories&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Educational Information]]&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Category:Herzing_University&amp;diff=69</id>
		<title>Category:Herzing University</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Category:Herzing_University&amp;diff=69"/>
		<updated>2026-01-12T15:34:10Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Reorganizing categories&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Educational Information]]&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Widget:NursingGame&amp;diff=1863</id>
		<title>Widget:NursingGame</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Widget:NursingGame&amp;diff=1863"/>
		<updated>2026-01-09T03:18:20Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Create widget&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;iframe src=&amp;quot;/htmlets/nursing-checkoff-study-game.html&amp;quot; style=&amp;quot;width:100%;height:850px;border:none;&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Template:GPTBot&amp;diff=3721</id>
		<title>Template:GPTBot</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Template:GPTBot&amp;diff=3721"/>
		<updated>2026-01-09T02:40:05Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Create GPTBot template&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
This template defines a GPT Bot configuration for use with [[Special:AIChat]].&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{{GPTBot&lt;br /&gt;
|name=Bot Name&lt;br /&gt;
|model=google/gemma-3-27b-it:free&lt;br /&gt;
|system_prompt=You are a helpful assistant...&lt;br /&gt;
|temperature=0.7&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parameters ==&lt;br /&gt;
* name - Display name for the bot&lt;br /&gt;
* model - OpenRouter model ID (default: google/gemma-3-27b-it:free)&lt;br /&gt;
* system_prompt - The system prompt that defines bot behavior&lt;br /&gt;
* temperature - Response creativity 0.0-1.0 (default: 0.7)&lt;br /&gt;
&lt;br /&gt;
[[Category:Bot Templates]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;&amp;lt;div class=&amp;quot;gptbot-config&amp;quot; style=&amp;quot;background:#f8f9fa; border:1px solid #a2a9b1; border-radius:4px; padding:15px; margin:10px 0;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:18px; font-weight:bold; margin-bottom:10px;&amp;quot;&amp;gt;🤖 {{{name|Unnamed Bot}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;table class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:0;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Model&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;&amp;lt;code&amp;gt;{{{model|google/gemma-3-27b-it:free}}}&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Temperature&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;{{{temperature|0.7}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;System Prompt&amp;lt;/th&amp;gt;&amp;lt;td style=&amp;quot;white-space:pre-wrap;&amp;quot;&amp;gt;{{{system_prompt|You are a helpful assistant.}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Category:GPT Bots]]&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Category:HU_NU_780_Population_Health&amp;diff=66</id>
		<title>Category:HU NU 780 Population Health</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Category:HU_NU_780_Population_Health&amp;diff=66"/>
		<updated>2026-01-08T16:11:06Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Create course category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Herzing University/Courses]]&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Category:HU_NU_730_Systems_Based_Practice&amp;diff=65</id>
		<title>Category:HU NU 730 Systems Based Practice</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Category:HU_NU_730_Systems_Based_Practice&amp;diff=65"/>
		<updated>2026-01-08T16:11:06Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Create course category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Herzing University/Courses]]&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Category:HU_NSG_633_Quality_and_Safety&amp;diff=64</id>
		<title>Category:HU NSG 633 Quality and Safety</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Category:HU_NSG_633_Quality_and_Safety&amp;diff=64"/>
		<updated>2026-01-08T16:11:05Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Create course category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Herzing University/Courses]]&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Category:HU_NSG_522_Clinical_I&amp;diff=63</id>
		<title>Category:HU NSG 522 Clinical I</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Category:HU_NSG_522_Clinical_I&amp;diff=63"/>
		<updated>2026-01-08T16:11:05Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Create course category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Herzing University/Courses]]&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Category:HU_NSG_521_Fundamental_Concepts_%26_Health_Assessment&amp;diff=62</id>
		<title>Category:HU NSG 521 Fundamental Concepts &amp; Health Assessment</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Category:HU_NSG_521_Fundamental_Concepts_%26_Health_Assessment&amp;diff=62"/>
		<updated>2026-01-08T16:11:05Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Create course category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Herzing University/Courses]]&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Category:HU_NSG_520_Pathophysiology_and_Pharmacology&amp;diff=61</id>
		<title>Category:HU NSG 520 Pathophysiology and Pharmacology</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Category:HU_NSG_520_Pathophysiology_and_Pharmacology&amp;diff=61"/>
		<updated>2026-01-08T16:11:04Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Create course category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Herzing University/Courses]]&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://wiki.xmethod.net/index.php?title=Category:HU_CR_021_Clinical_Readiness_Pre-licensure_Nursing&amp;diff=60</id>
		<title>Category:HU CR 021 Clinical Readiness Pre-licensure Nursing</title>
		<link rel="alternate" type="text/html" href="https://wiki.xmethod.net/index.php?title=Category:HU_CR_021_Clinical_Readiness_Pre-licensure_Nursing&amp;diff=60"/>
		<updated>2026-01-08T16:11:04Z</updated>

		<summary type="html">&lt;p&gt;Maintenance script: Create course category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Herzing University/Courses]]&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
</feed>