ตัวแก้ไขผู้ใช้โอเพนซอร์ซสำหรับ Safari
ผู้ใช้งานพร้อมใช้งานสำหรับ iOS (iPados) และ MacOS สำหรับทุกรุ่นการติดตั้งจะทำผ่าน App Store ของ Apple บน MacOS เวอร์ชันก่อนหน้า 4.x
ได้รับการดาวน์โหลดและติดตั้งโดยตรงจากที่เก็บ แต่เนื่องจากการเปลี่ยนแปลงในวิธีที่ Apple อนุญาตให้นักพัฒนาสามารถแจกจ่ายแอพที่สร้างขึ้นด้วย WEBEXTENSION API ซึ่งไม่ใช่ตัวเลือกอีกต่อไป
ในการเรียกใช้ Userscripts บน iOS คุณควรอยู่บน iOS 15.1 หรือสูงกว่า
ในการเรียกใช้ Userscripts บน MacOS คุณควรใช้ MacOS 12 หรือสูงกว่าพร้อมกับ Safari 14.1 หรือสูงกว่า
ลิงค์ App Store
ความก้าวหน้าในการพัฒนา
ขอแนะนำให้อ่านเอกสารนี้และหากคุณมีเวลาดูภาพรวมวิดีโอต่อไปนี้เพื่อทำความคุ้นเคยกับแอพและส่วนขยาย
เมื่อแอปถูกดาวน์โหลดและติดตั้งขั้นตอนต่อไปนี้ควรดำเนินการ:
หลังจากติดตั้งแอพ iOS คุณต้องมีสองขั้นตอนหลักในการทำงานส่วนขยาย:
เปิดแอพและตั้งค่าไดเรกทอรี (สำหรับการบันทึกและโหลด userscripts)
Set Userscripts Directory
และเลือกไดเรกทอรีเปิดใช้งานส่วนขยายใน Safari (และการอนุญาตให้)
AA
บน iPhone, extension-icon
บน iPad และที่คุณเปิดอินเทอร์เฟซ popup
ของส่วนขยาย)Always Allow
ผู้ใช้สำหรับ All Websites
บันทึก
แอปไม่สามารถตรวจพบได้ว่าคุณเปิดใช้งานส่วนขยายใน Safari หรือไม่ดังนั้นพรอมต์แอพจะไม่เปลี่ยนแปลงหลังจากที่คุณเปิดใช้งานส่วนขยาย ขณะนี้อินเทอร์เฟซแอพใช้เพื่อตั้งค่าหรือเปลี่ยนไดเรกทอรี userscripts เท่านั้น
คุณสามารถเลือกโฟลเดอร์ iCloud สำหรับการซิงค์สคริปต์ระหว่าง macOS และ iOS แต่โปรดทราบว่าอาจมีการล่าช้าในการซิงโครไนซ์และคุณอาจพบไฟล์ถูกขับไล่เนื่องจากการเพิ่มประสิทธิภาพ iCloud โปรดดู #424
มีสองวิธีหลักในการติดตั้งสคริปต์ผู้ใช้จากเวอร์ชัน iOS:
.user.js
url ใน Safari จากนั้นเปิด popup
อัพส่วนขยายและคุณจะเห็นพรอมต์การติดตั้ง.user.js
โดยตรงไปยังไดเรกทอรี usescripts ที่คุณตั้งไว้ด้านบน เคล็ดลับ
ทั้งสองทำงานได้ดีพอ ๆ กันในรุ่น MacOS
เวอร์ชัน iOS ไม่รวมตัวแก้ไขสคริปต์ที่มีให้ในเวอร์ชัน MACOS แต่คุณสามารถแก้ไขไฟล์สคริปต์ในไดเรกทอรีที่คุณตั้งค่าได้โดยตรงบน iOS (ใช้แอพตัวแก้ไขรหัสบุคคลที่สามสนับสนุนการเปิดและแก้ไขในสถานที่)
หลังจากติดตั้ง userscripts บน MacOS คุณ ไม่ จำเป็นต้องเลือกไดเรกทอรี Userscripts หากคุณไม่ได้วางแผนที่จะซิงค์ผู้ใช้งานระหว่างอุปกรณ์หลายเครื่อง แต่คุณสามารถเลือกใช้ไดเรกทอรีเริ่มต้นซึ่งอยู่ที่ ~/User/Library/Containers/Userscripts/Data/Documents/scripts
- อีกครั้งนี่คือพฤติกรรมเริ่มต้น (และอัตโนมัติ) คุณจะต้องเลือกตำแหน่งใหม่หากคุณต้องการจัดเก็บผู้ใช้งานของคุณที่อื่นซึ่งมีประโยชน์อย่างยิ่งหากคุณใช้โปรแกรมแก้ไขรหัสภายนอกเช่นข้อความประเสริฐหรือ VSCODE
อ้างถึงหน้าคู่มืออย่างเป็นทางการของ Apple: ใช้ส่วนขยาย Safari บน Mac ของคุณ
นี่คือคลิปสั้น ๆ ที่แสดงวิธีสร้าง/เพิ่มผู้ใช้ใน Safari ได้อย่างง่ายดายโดยใช้ส่วนขยายนี้บน macOS
settings
(แสดงโดย COG) แสดงการตั้งค่า Modal (กล่าวถึงด้านล่าง)plus
ช่วยให้ผู้ใช้สามารถเพิ่มรายการใหม่New CSS
เป็น "ผู้ใช้" ที่คาดว่าจะมีรหัส CSSNew Javascript
เป็นผู้ใช้ต้นแบบที่คาดว่าจะมีรหัส JavaScriptNew Remote
อนุญาตให้ผู้ใช้เพิ่มผู้ใช้โฮสต์ระยะไกล (หรือสไตล์) โดยการป้อนที่อยู่เว็บ ( เช่น: https://www.k21p.com/example.user.js
)@version
@updateURL
Discard
- ในขณะที่แก้ไขให้เปลี่ยนการเปลี่ยนแปลงที่ไม่ได้บันทึกใด ๆ ที่คุณทำกับ UserscriptSave
- ในขณะที่การแก้ไขบันทึกการเปลี่ยนแปลงทั้งหมดที่คุณทำกับ UserscriptCommand + S
เป็นแป้นพิมพ์ลัดสำหรับการดำเนินการ() [] {} "" ''
4
เพราะการใช้ 2
ช่องว่างเป็นความวิกลจริตแบบสัมบูรณ์@match
(โครงสร้างรูปแบบการจับคู่) url หน้าเว็บที่ตรงกับรูปแบบในรายการนี้จะถูกละเว้นสำหรับการฉีดสคริปต์ปัจจุบันผู้ใช้ Safari รองรับข้อมูลเมตาผู้ใช้ต่อไปนี้:
@name
- นี่จะเป็นชื่อที่แสดงในแถบด้านข้างและใช้เป็นชื่อไฟล์ - คุณ ไม่ สามารถใช้ชื่อเดียวกันสำหรับหลายไฟล์ประเภทเดียวกัน@description
- ใช้สิ่งนี้เพื่ออธิบายสิ่งที่ผู้ใช้ของคุณทำ - จะแสดงในแถบด้านข้าง - มีการตั้งค่าเพื่อซ่อนคำอธิบาย@icon
- นี่ไม่มีฟังก์ชั่นกับตัวจัดการผู้ใช้งานนี้ แต่ ค่าแรก ที่ให้ไว้ในข้อมูลเมตาจะสามารถเข้าถึงได้ในวัตถุ GM_/GM.info
@match
- รูปแบบการจับคู่โดเมน - คุณสามารถใช้หลายอินสแตนซ์ของฟิลด์นี้หากคุณต้องการการจับคู่โดเมนหลายรายการ - โปรดดูที่: โครงสร้างรูปแบบการจับคู่http/s
เท่านั้น@exclude-match
- รูปแบบโดเมนที่คุณ ไม่ ต้องการให้สคริปต์รัน@include
- ใช้เพื่อจับคู่กับ URL สำหรับการฉีดลูกโลกและการแสดงออกปกติอ่านเพิ่มเติมได้ที่นี่@exclude
- ฟังก์ชั่นในลักษณะเดียวกันกับ @include
แต่แทนที่จะฉีดการจับคู่กับค่าของคีย์นี้จะป้องกันการฉีด@inject-into
- อนุญาตให้ผู้ใช้เลือกบริบทที่จะฉีดสคริปต์ลงไปauto
(ค่าเริ่มต้น), content
, page
GM
API นั้นใช้ได้เฉพาะเมื่อใช้ content
@run-at
@weight
@require
@version
@updateURL
สิ่งนี้จะช่วยให้ผู้ใช้อัปเดตผู้ใช้จากแหล่งข้อมูลระยะไกลหากเวอร์ชันในเครื่องของพวกเขาคือ <
เวอร์ชันที่ UDD URL@version
ไม่ทำอะไรด้วยตัวเองมันจะต้องจับคู่กับ @updateURL
สำหรับการอัปเดตระยะไกลเพื่อให้ทำงานได้อย่างถูกต้อง@updateURL
>
@updateURL
ไม่ได้ทำอะไรด้วยตัวเองมันจะต้องจับคู่กับ @version
สำหรับการอัปเดตระยะไกลเพื่อทำงานอย่างถูกต้อง@downloadURL
@version
และ @updateURL
)@version
และ @updateURL
หากเวอร์ชันท้องถิ่นคือ <
เวอร์ชันของไฟล์ที่ @updateURL
ชี้ไปที่ส่วนขยายจะพยายามอัปเดตรหัสของไฟล์ด้วยเนื้อหาของไฟล์ที่อยู่ที่ @downloadURL
@downloadURL
ไม่ได้ทำอะไรด้วยตัวเองมันต้องการ @version
และ @updateURL
เพื่อนำเสนอเพื่อให้ทำงานได้อย่างถูกต้อง@noframes
@grant
APIs
พิเศษ (ถ้ามี) ของคุณใช้หนึ่งในแต่ละบรรทัด @grant
แต่ละบรรทัดจะมีวิธี API เหล่านั้นเท่านั้น@grant
จะ none
การสันนิษฐานnone
และอย่างอื่น none
ความสำคัญ ผู้ใช้ทั้งหมดต้องการอย่างน้อย 1 @match
หรือ @include
เพื่อเรียกใช้!
ปัจจุบันผู้ใช้งานสนับสนุนวิธี API ต่อไปนี้ วิธีการทั้งหมดเป็นแบบอะซิงโครนัสเว้นแต่จะระบุไว้เป็นอย่างอื่น ผู้ใช้จะต้อง @grant
วิธีการเหล่านี้เพื่อใช้ในผู้ใช้ เมื่อใช้วิธี API เป็นไปได้ที่จะฉีดเข้าไปในขอบเขตสคริปต์เนื้อหาเนื่องจากความกังวลด้านความปลอดภัย
บันทึก
คำอธิบาย API ต่อไปนี้ใช้กับสาขาการพัฒนาล่าสุดคุณอาจต้องตรวจสอบเอกสารสำหรับเวอร์ชันที่เกี่ยวข้อง โปรดเปลี่ยนเป็นเวอร์ชันที่คุณต้องการตรวจสอบผ่าน Branches
หรือ Tags
ที่ด้านบน
ตัวอย่างเช่นสำหรับ App Store เวอร์ชัน v4.xx: https://github.com/quoid/userscripts/tree/release/4.xx
สำหรับคำจำกัดความประเภท API โปรดดู: types.d.ts
GM.addStyle(css)
css: String
Promise
ที่ได้รับการแก้ไขหากประสบความสำเร็จปฏิเสธด้วยข้อความแสดงข้อผิดพลาดหากล้มเหลวGM.setValue(key, value)
key: String
value: Any
- ใด ๆ ที่สามารถ json -serializedPromise
ที่ได้รับการแก้ไขหากประสบความสำเร็จปฏิเสธด้วยข้อความแสดงข้อผิดพลาดหากล้มเหลวGM.getValue(key, defaultValue)
key: String
defaultValue: Any
- ไม่บังคับPromise
ที่ได้รับการแก้ไขด้วย value
ที่ตั้งไว้หรือ defaultValue
ที่ให้ไว้หรือ undefined
หากสำเร็จจะถูกปฏิเสธด้วยข้อความแสดงข้อผิดพลาดหากล้มเหลวGM.deleteValue(key)
key: String
Promise
ที่ได้รับการแก้ไขหากประสบความสำเร็จปฏิเสธด้วยข้อความแสดงข้อผิดพลาดหากล้มเหลวGM.listValues()
Promise
ที่ได้รับการแก้ไขด้วยอาร์เรย์ของชื่อคีย์ของค่า ที่ตั้งไว้ในปัจจุบัน หากสำเร็จโดยปฏิเสธด้วยข้อความแสดงข้อผิดพลาดหากล้มเหลวGM.getTab()
Promise
ที่ได้รับการแก้ไขด้วยข้อมูล Any
ที่คงอยู่ตราบใดที่แท็บนี้เปิดอยู่หากประสบความสำเร็จปฏิเสธด้วยข้อความแสดงข้อผิดพลาดหากล้มเหลวGM.saveTab(tabObj)
tabObj: Any
- ใด ๆ ที่สามารถ json -serializedPromise
ที่ได้รับการแก้ไขหากประสบความสำเร็จปฏิเสธด้วยข้อความแสดงข้อผิดพลาดหากล้มเหลวGM.openInTab(url, openInBackground)
url: String
openInBackground: Bool
- เป็นตัวเลือก, false
โดยค่าเริ่มต้นPromise
ที่ได้รับการแก้ไขด้วยข้อมูล TAB สำหรับแท็บที่เพิ่งเปิดหากประสบความสำเร็จปฏิเสธด้วยข้อความแสดงข้อผิดพลาดหากล้มเหลวGM.closeTab(tabId)
tabId: Int
- ไม่บังคับ caller tab
ตามค่าเริ่มต้นPromise
ที่ได้รับการแก้ไขหากประสบความสำเร็จปฏิเสธด้วยข้อความแสดงข้อผิดพลาดหากล้มเหลวGM.setClipboard(data, type)
data: String
type: String
- ตัวเลือก text/plain
โดยค่าเริ่มต้นPromise
ที่ได้รับการแก้ไขด้วยค่า Bool
ที่ระบุว่าประสบความสำเร็จหรือล้มเหลวปฏิเสธด้วยข้อความแสดงข้อผิดพลาดหากล้มเหลวGM.info
&& GM_info
@grant
scriptHandler: String
- return Userscripts
version: String
- แอพเวอร์ชัน UserscriptsscriptMetaStr: String
- The Metablock สำหรับสคริปต์ที่กำลังทำงานอยู่ในปัจจุบันscript: Object
- มีข้อมูลเกี่ยวกับสคริปต์ที่กำลังทำงานอยู่ในปัจจุบันdescription: String
exclude-match: [String]
excludes: [String]
grant: [String]
includes: [String]
inject-into: String
matches: [String]
name: String
namespace: String
noframes: Bool
require: [String]
resources: [String]
- ปัจจุบันยังไม่ได้ใช้งานrun-at: String
version: String
- ค่าเวอร์ชัน UserscriptGM.xmlHttpRequest(details)
details: Object
details
ยอมรับคุณสมบัติต่อไปนี้url: String
- จำเป็นmethod: String
- ไม่บังคับ GET
ตามค่าเริ่มต้นuser: String
- เสริมpassword: String
- เป็นทางเลือกheaders: Object
- เป็นทางเลือกoverrideMimeType: String
- เป็นตัวเลือกtimeout: Int
- ไม่บังคับbinary: Bool
- เป็นตัวเลือก (เลิกใช้แล้ว, ใช้วัตถุข้อมูลไบนารีเช่น Blob
, ArrayBuffer
, TypedArray
ฯลฯ แทน)data: String | Blob | ArrayBuffer | TypedArray | DataView | FormData | URLSearchParams
- เป็นทางเลือกresponseType: String
- ไม่บังคับXMLHttpRequests
onabort: Function
- ไม่บังคับonerror: Function
- ไม่บังคับonload: Function
- เป็นทางเลือกonloadend: Function
- ไม่บังคับonloadstart: Function
- ไม่บังคับonprogress: Function
- ไม่บังคับonreadystatechange: Function
- ไม่บังคับontimeout: Function
- ไม่บังคับreadyState
response
responseHeaders
responseType
responseURL
status
statusText
timeout
responseText
(เมื่อ responseType
เป็น text
)Promise
ที่กำหนดเองมี abort
คุณสมบัติเพิ่มเติมแก้ไขด้วยวัตถุตอบกลับconst xhr = GM.xmlHttpRequest({...});
xhr.abort();
ยกเลิกคำขอconst response = await xhr;
const response = await GM.xmlHttpRequest({...});
GM_xmlhttpRequest(details)
GM.xmlHttpRequest(details)
ยกเว้น:abort
ซึ่งเป็น Function
const foo = GM.xmlHttpRequest({...});
... foo.abort();
ยกเลิกคำขอ นี่คือไดเรกทอรีที่แอพ/ส่วนขยายจะอ่านและเขียนถึง ไดเรกทอรีนี้มีการเปลี่ยนแปลงโดยการเปิด แอพที่มีอยู่ และคลิกปุ่ม "เปลี่ยนตำแหน่ง" ที่เกี่ยวข้อง
บันทึกไดเรกทอรีสคริปต์
หากคุณพบปัญหาในขณะที่ใช้แอพ/ส่วนขยายนี้หรือต้องการความช่วยเหลือบางอย่างโปรดเปิดปัญหาที่นี่ในที่เก็บ เมื่อทำเช่นนั้นโปรดให้รายละเอียดมากที่สุด ซึ่งรวมถึงข้อมูลจำเพาะระบบรายชื่อและเว็บไซต์และสคริปต์ที่คุณพยายามดำเนินการ โปรดติดตามเทมเพลตปัญหา!
"ปฏิเสธที่จะเรียกใช้สคริปต์" ข้อผิดพลาดฉันควรทำอย่างไร!
คุณเห็นข้อผิดพลาดนี้เนื่องจากนโยบายความปลอดภัยเนื้อหาของเว็บไซต์ ขณะนี้ไม่มีวิธีที่จะอนุญาตให้สคริปต์เนื้อหาส่วนขยายผ่าน CSPS ใน Safari
โดยอัตโนมัติส่วนขยายจะพยายามหลีกเลี่ยง CSP ที่เข้มงวด แต่ถ้าคุณยังคงประสบปัญหาลองตั้งค่าคีย์เมตาดาต้า Userscript // val
// @inject-into auto
หรือ// @inject-into content
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ในฉบับนี้
ฉันจำเป็นต้องใช้ตัวแก้ไขของส่วนขยายเพื่อสร้างผู้ใช้ใหม่หรือเพื่อแก้ไขที่มีอยู่หรือไม่?
คุณสามารถใช้ตัวแก้ไขของคุณเองเพื่ออัปเดตและจัดการไฟล์ของคุณ ตราบใดที่คุณกำลังบันทึกไฟล์ไปยังตำแหน่งที่บันทึกไว้และมีการจัดรูปแบบอย่างเหมาะสมพวกเขาควรได้รับการฉีด อย่างไรก็ตามคุณ ต้องเปิดป๊อปอัพส่วนขยาย ล่วงหน้า นั่นหมายความว่าหากคุณสร้างใหม่หรือแก้ไขผู้ใช้ที่มีอยู่ด้วยตัวแก้ไขภายนอกและบันทึกลงในตำแหน่งบันทึกก่อนที่จะฉีดจะเกิดขึ้นอย่างถูกต้องควรเปิดป๊อปอัพส่วนขยายและป๊อปอัปจะต้องโหลดอย่างสมบูรณ์
แป้นพิมพ์ลัดคืออะไร?
ในขณะที่ใช้ตัวแก้ไขที่รวมอยู่การคลิก
⌘ + s
จะบันทึกไฟล์ ในขณะที่ทำงานตัวแก้ไขการคลิก⌘ + f
จะเปิดแถบค้นหาและesc
จะซ่อนมันไว้
เมื่อฉันใช้ @require
ไฟล์ที่ต้องการจะถูกเก็บไว้ที่ไหน
ไฟล์ที่ต้องการทั้งหมดจะถูกบันทึก เป็นไฟล์ JavaScript ในโฟลเดอร์ Container Extension ใน MacOS 11.x โฟลเดอร์นั้นอยู่ในตำแหน่งบันทึกเริ่มต้นที่:
~/Library/Containers/Userscripts/Data/Documents/require/
หากคุณย้ายไฟล์จากโฟลเดอร์ที่ต้องการหรือแก้ไขไฟล์
manifest.json
ด้วยตนเองคุณอาจทำลายฟังก์ชันแอพ/ส่วนขยาย
การบริจาคระดับรหัสโปรดดูที่การสนับสนุน. md
นอกจากนี้ปัญหาใด ๆ ที่ทำเครื่องหมายไว้ "ต้องการความช่วยเหลือ" กำลังขอความช่วยเหลืออย่างแข็งขัน โปรดตอบสนองต่อปัญหาเหล่านั้นด้วยข้อเสนอแนะคำแนะนำหรือข้อเสนอของความช่วยเหลือการเข้ารหัส
การเข้าร่วมและโต้ตอบกับ Issues
หรือ Discussions
ที่มีอยู่จะเป็นความช่วยเหลือที่ดีสำหรับโครงการและชุมชนโอเพ่นซอร์ส ขอบคุณสำหรับการมีส่วนร่วมของคุณ
วิธีที่เร็วที่สุดและง่ายที่สุดในการสนับสนุนโครงการคือการทิ้งรีวิวในเชิงบวกใน App Store หากคุณสนุกกับการขยายและต้องการดูการปรับปรุงในอนาคต การเห็นบทวิจารณ์เหล่านี้แจ้งให้เราทราบว่าฉันกำลังทำสิ่งที่ถูกต้องหรือผิดและกระตุ้นให้ฉันทำงานต่อไปในโครงการต่อไป
วิธีที่ดีที่สุดอันดับสองในการช่วยเหลือคือการลงทะเบียนเพื่อทดสอบเบต้าเวอร์ชันใหม่ของแอพ เนื่องจากส่วนขยายนี้ให้ความสำคัญกับความเป็นส่วนตัวของคุณและ ไม่ได้รวบรวมข้อมูลใด ๆ จากผู้ใช้ จึงเป็นเรื่องยากที่จะวัดว่ามีการใช้ส่วนขยายอย่างไร โดยการลงทะเบียนเป็นเครื่องทดสอบเบต้าไม่เพียง แต่ช่วยให้คุณทดสอบคุณสมบัติที่กำลังจะมาถึง แต่ยังเปิดโอกาสให้ฉันได้รับการตอบรับโดยตรงจากผู้ใช้จริง
โปรดเข้าร่วมและทดสอบรุ่นเบต้าที่เกี่ยวข้องในรุ่นผ่านลิงก์สาธารณะ TestFlight
ผู้ใช้ไม่ได้รวบรวมข้อมูลใด ๆ จากผู้ใช้หรือตรวจสอบกิจกรรมหรือการกระทำที่คุณดำเนินการภายในแอปพลิเคชันและส่วนขยาย ซึ่งหมายความว่าทุกสิ่งที่คุณทำกับแอปพลิเคชันและส่วนขยายเป็นเรื่องส่วนตัวสำหรับคุณและไม่เคยแบ่งปันกับนักพัฒนาหรือบุคคลที่สาม เนื่องจากไม่มีการรวบรวมข้อมูลจึงไม่มีการเก็บข้อมูลใด ๆ
ลิขสิทธิ์ (c) 2018-2024 Justin Wasack
ได้รับใบอนุญาตภายใต้ใบอนุญาตสาธารณะ GNU ทั่วไป v3.0 ใบอนุญาตสำหรับแอปพลิเคชันโอเพ่นซอร์สทั้งหมด จำเป็นต้องมีใบอนุญาตเชิงพาณิชย์สำหรับแอปพลิเคชันอื่น ๆ ทั้งหมด