PageSourceSearch

https://ytyaru.github.io/Html.Mastodon.Account.Info.20220611094830/js/tweet-button.js

js ytyaru.github.io collected 2026-10-03 10:14:09 UTC 5,492 bytes, 94 lines download raw bytes

1class TweetButton extends HTMLElement {
2    /*
3    <tweet-button
4      text="ツイートしたい内容\n改行"
5      url="ツイートに含めたいURL"
6      hashtags="tag1,tag2,tag3"
7      title="マウスオーバーで表示される"
8      src="https://example.com/tweet-button.svg"
9      size="64"
10    ></tweet-button>
11    */
12    constructor(domain) {
13        super();
14        this.text = null
15        this.url = location.href
16        this.hashtags = null
17        this._title = null // 変数名をthis.titleにしてしまうと"null"というテキストになってしまう!
18        this.src = null
19        this.size = '64'
20    }
21    static get observedAttributes() {
22        return ['text', 'url', 'hashtags', 'title', 'src', 'size'];
23    }
24    async connectedCallback() {
25        const shadow = this.attachShadow({ mode: 'closed' });
26        //const shadow = this.attachShadow({ mode: 'open' }); // マウスイベント登録に必要だった。CSS的にはclosedにしたいのに。
27        const gen = new TweetButtonGenerator()
28        const button = await gen.generate(this.#getOptions())
29        shadow.innerHTML = button.outerHTML
30        //shadow.innerHTML = `<style>${this.#cssBase()}</style>${button.outerHTML}`
31    }
32    attributeChangedCallback(property, oldValue, newValue) {
33        if (oldValue === newValue) { return; }
34        else if ('text' === property) { this.text = newValue.replace('\\n', '\n') }
35        else if ('size' === property) { this.size = parseInt(newValue) }
36        else { this[property] = newValue; }
37    }
38    #getOptions() {
39        const options = {}
40        if (this.text) { options.text = this.text }
41        if (this.url) { options.url = this.url }
42        if (this.hashtags) { options.hashtags = this.hashtags }
43        if (this._title) { options.title = this._title }
44        if (this.src) { options.src = this.src }
45        if (this.size) { options.size = this.size }
46        console.log(options)
47        return options
48    }
49    #cssBase() { return `img{cursor:pointer; text-align:center; vertical-align:middle; user-select:none;}` }
50}
51window.addEventListener('DOMContentLoaded', (event) => {
52    customElements.define('tweet-button', TweetButton);
53});
54class TweetButtonGenerator {
55    constructor() {
56        this.options = null
57    }
58    async generate(options) {
59        this.options = options
60        console.log(options)
61        const a = await this.#makeA(options)
62        const img = this.#makeImg(options)
63        a.appendChild(img)
64        return a
65    }
66    async #makeA() {
67        const a = document.createElement('a')
68        const url = new URL('https://twitter.com/share')
69        console.log(this.options)
70        if (this.options.hasOwnProperty('text') && this.options.text) { url.searchParams.set('text', this.options.text + await this.#getAddress()) }
71        if (this.options.hasOwnProperty('url') && this.options.url) { url.searchParams.set('url', this.options.url + '\n' + this.#getBridgy()) }
72        if (this.options.hasOwnProperty('hashtags') && this.options.hashtags) { url.searchParams.set('hashtags', this.options.hashtags) }
73        a.setAttribute('href', url.href)
74        a.setAttribute('target', '_blank')
75        a.setAttribute('rel', 'noopener noreferrer')
76        if (this.options.hasOwnProperty('title') && this.options.title) { a.setAttribute('title', this.options.title) }
77        return a
78    }
79    async #getAddress() { return (window.hasOwnProperty('mpurse')) ? '\n' + await window.mpurse.getAddress() : '' }
80    #getBridgy() { return 'https://brid.gy/publish/twitter' } // https://brid.gy/about#webmentions
81    #makeImg() {
82        const img = document.createElement('img')
83        img.classList.add('tweet-button')
84        const size = (this.options.hasOwnProperty('size')) ? this.options.size : 64
85        img.setAttribute('width', size)
86        img.setAttribute('height', size)
87        img.setAttribute('src', this.#getImgSrc(this.options))
88        return img
89    }
90    #getImgSrc() {
91        if (this.options.hasOwnProperty('src')) { return this.options.src }
92        return `data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8yIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDQwMCA0MDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQwMCA0MDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsOiMxQjlERjA7fQ0KCS5zdDF7ZmlsbDojRkZGRkZGO30NCjwvc3R5bGU+DQo8ZyBpZD0iRGFya19CbHVlIj4NCgk8Y2lyY2xlIGNsYXNzPSJzdDAiIGN4PSIyMDAiIGN5PSIyMDAiIHI9IjIwMCIvPg0KPC9nPg0KPGcgaWQ9IkxvZ29fX3gyMDE0X19GSVhFRCI+DQoJPHBhdGggY2xhc3M9InN0MSIgZD0iTTE2My40LDMwNS41Yzg4LjcsMCwxMzcuMi03My41LDEzNy4yLTEzNy4yYzAtMi4xLDAtNC4yLTAuMS02LjJjOS40LTYuOCwxNy42LTE1LjMsMjQuMS0yNQ0KCQljLTguNiwzLjgtMTcuOSw2LjQtMjcuNyw3LjZjMTAtNiwxNy42LTE1LjQsMjEuMi0yNi43Yy05LjMsNS41LTE5LjYsOS41LTMwLjYsMTEuN2MtOC44LTkuNC0yMS4zLTE1LjItMzUuMi0xNS4yDQoJCWMtMjYuNiwwLTQ4LjIsMjEuNi00OC4yLDQ4LjJjMCwzLjgsMC40LDcuNSwxLjMsMTFjLTQwLjEtMi03NS42LTIxLjItOTkuNC01MC40Yy00LjEsNy4xLTYuNSwxNS40LTYuNSwyNC4yDQoJCWMwLDE2LjcsOC41LDMxLjUsMjEuNSw0MC4xYy03LjktMC4yLTE1LjMtMi40LTIxLjgtNmMwLDAuMiwwLDAuNCwwLDAuNmMwLDIzLjQsMTYuNiw0Mi44LDM4LjcsNDcuM2MtNCwxLjEtOC4zLDEuNy0xMi43LDEuNw0KCQljLTMuMSwwLTYuMS0wLjMtOS4xLTAuOWM2LjEsMTkuMiwyMy45LDMzLjEsNDUsMzMuNWMtMTYuNSwxMi45LTM3LjMsMjAuNi01OS45LDIwLjZjLTMuOSwwLTcuNy0wLjItMTEuNS0wLjcNCgkJQzExMC44LDI5Ny41LDEzNi4yLDMwNS41LDE2My40LDMwNS41Ii8+DQo8L2c+DQo8L3N2Zz4NCg0K`
93    }
94}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.