Extension to return old Twitter layout from 2015.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

testing locales and npm init

dimden ce73db27 1cae8107

+161 -9
+2 -2
.github/workflows/pack.yml
··· 19 19 uses: actions/setup-node@v2.5.2 20 20 21 21 - name: Setup NPM packages 22 - run: npm i adm-zip 22 + run: npm install 23 23 24 24 - name: Pack extension 25 - run: node pack.js 25 + run: npm run build 26 26 27 27 - name: Upload for Firefox 28 28 uses: actions/upload-artifact@v3.1.2
+25
.github/workflows/test.yml
··· 1 + name: Test locales 2 + 3 + on: 4 + push: 5 + branches: [ "master" ] 6 + pull_request: 7 + branches: [ "master" ] 8 + 9 + jobs: 10 + test: 11 + 12 + runs-on: windows-latest 13 + 14 + steps: 15 + - name: Checkout Source Tree 16 + uses: actions/checkout@v3 17 + 18 + - name: Setup Node.js environment 19 + uses: actions/setup-node@v2.5.2 20 + 21 + - name: Setup NPM packages 22 + run: npm install 23 + 24 + - name: Test locales 25 + run: npm run test
+3 -1
.gitignore
··· 1 - _metadata/ 1 + _metadata/ 2 + node_modules/ 3 + package-lock.json
+2 -2
_locales/ar/messages.json
··· 1 1 { 2 - "ext_description": { "message": "امتداد جديد يعيد مظهرامتداد جديد يعيد مظهر Twitter القديم.", "translator_note": "There is still some confusion if Twitter is to be written as تويتر or Twitter. For now I have arbritarirly put it the latter. Also note that 'tweet' in official translation is given literally as chirp so I had changed it to تويت, and that this is not a mistake" }, 2 + "ext_description": { "message": "امتداد جديد يعيد مظهرامتداد جديد يعيد مظهر Twitter القديم.", "note": "There is still some confusion if Twitter is to be written as تويتر or Twitter. For now I have arbritarirly put it the latter. Also note that 'tweet' in official translation is given literally as chirp so I had changed it to تويت, and that this is not a mistake" }, 3 3 "timeline": { "message": "الجدول الزمني" }, 4 4 "loading": { "message": "جار التحميل" }, 5 5 "tweets": { "message": "تغريدات" }, ··· 26 26 "profile": { "message": "الملف الشخصيّ" }, 27 27 "settings": { "message": "الإعدادات" }, 28 28 "lists": { "message": "القوائم" }, 29 - "تحدي": { "message": "قائمة" }, 29 + "list": { "message": "قائمة" }, 30 30 "bookmarks": { "message": "العلامات المرجعية" }, 31 31 "manage_accounts": { "message": "إدارة الحسابات" }, 32 32 "logout": { "message": "تسجيل خروج" },
+2 -3
_locales/ko/messages.json
··· 12 12 "who_to_follow": { "message": "팔로우 추천", "description": "Max 19 characters, you can use word 'People' if no space" }, 13 13 "refresh": { "message": "새로고침" }, 14 14 "view_all": { "message": "모두 보기" }, 15 - "running": { "message": "", "memo": "Korean Remove Running message because of grammer differance" }, 15 + "running": { "message": "", "note": "Korean Remove Running message because of grammer differance" }, 16 16 "created_by": { "message": "제작자", "example": "->Created by<- dimden" }, 17 17 "website": { "message": "웹사이트" }, 18 18 "help": { "message": "고객지원", "description": "noun" }, ··· 259 259 "replying_to_tweet": { "message": "트윗에 대한 답글" }, 260 260 "upload_media_btn": { "message": "[미디어 업로드]" }, 261 261 "cancel_btn": { "message": "[취소]" }, 262 - "quote": { "message": "인용","memo":"원래 인용하기가 맞을지도" }, 262 + "quote": { "message": "인용", "note":"원래 인용하기가 맞을지도" }, 263 263 "reply_example": { "message": "답글로 초멘나사이는 적지 마세요" }, 264 264 "quote_example": { "message": "추가 내용" }, 265 265 "error_sending_tweet": { "message": "트윗 전송 오류" }, ··· 403 403 "block_sure_desc": { "message": "이제 @$SCREEN_NAME$ 님은 더이상 나를 팔로우 하거나 쪽지를 보낼 수 없습니다.", "placeholders": { "screen_name": { "content": "CoolPerson2000" } } }, 404 404 "blocked_by_user" : { "message": "@$SCREEN_NAME$ 님이 나를 차단했습니다.", "placeholders": { "screen_name": { "content": "CoolPerson2000" } } }, 405 405 "why_you_cant_see_block_user": { "message": "@$SCREEN_NAME$ 님을 팔로우 하거나 @$SCREEN_NAME$ 님의 트윗을 볼 수 없습니다", "placeholders": { "screen_name": { "content": "CoolPerson2000" } } } 406 - 407 406 }
+7 -1
pack.js
··· 9 9 const entries = await fsp.readdir(src, { withFileTypes: true }); 10 10 await fsp.mkdir(dest); 11 11 for (let entry of entries) { 12 - if(entry.name === '.git' || entry.name === '.github' || entry.name === '_metadata') continue; 12 + if(entry.name === '.git' || entry.name === '.github' || entry.name === '_metadata' || entry.name === 'node_modules') continue; 13 13 const srcPath = path.join(src, entry.name); 14 14 const destPath = path.join(dest, entry.name); 15 15 if (entry.isDirectory()) { ··· 215 215 fs.unlinkSync('../OldTwitterFirefox/scripts/background_v2.js'); 216 216 fs.unlinkSync('../OldTwitterFirefox/.gitignore'); 217 217 fs.unlinkSync('../OldTwitterTempChrome/.gitignore'); 218 + fs.unlinkSync('../OldTwitterFirefox/test.js'); 219 + fs.unlinkSync('../OldTwitterTempChrome/test.js'); 220 + fs.unlinkSync('../OldTwitterFirefox/package.json'); 221 + fs.unlinkSync('../OldTwitterTempChrome/package.json'); 222 + fs.unlinkSync('../OldTwitterFirefox/package-lock.json'); 223 + fs.unlinkSync('../OldTwitterTempChrome/package-lock.json'); 218 224 219 225 let layouts = fs.readdirSync('../OldTwitterFirefox/layouts'); 220 226 for (let layout of layouts) {
+32
package.json
··· 1 + { 2 + "name": "oldtwitter", 3 + "version": "0.0.0", 4 + "description": "Extension to return old Twitter layout from 2015.", 5 + "main": "pack.js", 6 + "scripts": { 7 + "test": "node test.js", 8 + "build": "node pack.js" 9 + }, 10 + "repository": { 11 + "type": "git", 12 + "url": "git+https://github.com/dimdenGD/OldTwitter.git" 13 + }, 14 + "keywords": [ 15 + "twitter", 16 + "twitter-client", 17 + "chrome-extension", 18 + "firefox-addons", 19 + "chrome", 20 + "firefox-extension", 21 + "chromium-extension" 22 + ], 23 + "author": "dimden", 24 + "license": "UNLICENSED", 25 + "bugs": { 26 + "url": "https://github.com/dimdenGD/OldTwitter/issues" 27 + }, 28 + "homepage": "https://github.com/dimdenGD/OldTwitter#readme", 29 + "dependencies": { 30 + "adm-zip": "^0.5.10" 31 + } 32 + }
+88
test.js
··· 1 + // Tests locale files 2 + 3 + const fs = require('fs'); 4 + const path = require('path'); 5 + 6 + const validKey = /^[a-zA-Z0-9_@]+$/; 7 + const placeholdersRegex = /\$[a-zA-Z0-9_@]+\$/g; 8 + const validFieldKeys = ['name', 'message', 'description', 'example', 'placeholders']; 9 + 10 + const locales = 11 + fs.readdirSync(path.join(__dirname, '_locales'), { withFileTypes: true }) 12 + .filter(dirent => dirent.isDirectory()) 13 + .map(dirent => dirent.name); 14 + 15 + let errors = false; 16 + 17 + for(let localeName of locales) { 18 + let locale; 19 + 20 + try { 21 + locale = JSON.parse(fs.readFileSync(path.join(__dirname, '_locales', localeName, 'messages.json'))); 22 + } catch(e) { 23 + console.error(`(Critical) Error parsing _locales/${localeName}/messages.json`, e); 24 + errors = true; 25 + continue; 26 + } 27 + 28 + let keys = Object.keys(locale); 29 + for(let key of keys) { 30 + if(!validKey.test(key)) { 31 + console.error(`Invalid key "${key}" in _locales/${localeName}/messages.json`); 32 + errors = true; 33 + } 34 + if(key.length > 80) { 35 + console.error(`Key "${key}" is too long in _locales/${localeName}/messages.json`); 36 + errors = true; 37 + } 38 + } 39 + 40 + if(!locale.ext_description) { 41 + console.error(`Missing "ext_description" in _locales/${localeName}/messages.json`); 42 + errors = true; 43 + } 44 + 45 + if(locale.ext_description.length > 132) { 46 + console.error(`"ext_description" is too long in _locales/${localeName}/messages.json`); 47 + errors = true; 48 + } 49 + 50 + for(let fieldName in locale) { 51 + let field = locale[fieldName]; 52 + let keys = Object.keys(field); 53 + 54 + for(let key of keys) { 55 + if(!validFieldKeys.includes(key)) { 56 + console.error(`Invalid key "${key}" on "${fieldName}" in _locales/${localeName}/messages.json`); 57 + errors = true; 58 + } 59 + } 60 + 61 + if(typeof field.message !== 'string') { 62 + console.error(`Missing "message" on "${fieldName}" in _locales/${localeName}/messages.json`); 63 + errors = true; 64 + } 65 + 66 + let placeholders = field.message.match(placeholdersRegex); 67 + if(placeholders) { 68 + if(!field.placeholders) { 69 + console.error(`Missing "placeholders" on "${fieldName}" in _locales/${localeName}/messages.json`); 70 + errors = true; 71 + } else { 72 + placeholders = placeholders.map(placeholder => placeholder.slice(1, -1).toLowerCase()); 73 + for(let placeholder of placeholders) { 74 + if(!field.placeholders[placeholder]) { 75 + console.error(`Missing placeholder "${placeholder}" on "${fieldName}" in _locales/${localeName}/messages.json`); 76 + errors = true; 77 + } 78 + } 79 + } 80 + } 81 + } 82 + } 83 + 84 + if(errors) { 85 + process.exit(1); 86 + } 87 + 88 + console.log('All locale files are valid.');