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.