Wikisource
viwikisource
https://vi.wikisource.org/wiki/Trang_Ch%C3%ADnh
MediaWiki 1.47.0-wmf.1
first-letter
Phương tiện
Đặc biệt
Thảo luận
Thành viên
Thảo luận Thành viên
Wikisource
Thảo luận Wikisource
Tập tin
Thảo luận Tập tin
MediaWiki
Thảo luận MediaWiki
Bản mẫu
Thảo luận Bản mẫu
Trợ giúp
Thảo luận Trợ giúp
Thể loại
Thảo luận Thể loại
Chủ đề
Thảo luận Chủ đề
Tác gia
Thảo luận Tác gia
Trang
Thảo luận Trang
Mục lục
Thảo luận Mục lục
Biên dịch
Thảo luận Biên dịch
TimedText
TimedText talk
Mô đun
Thảo luận Mô đun
Event
Event talk
Đề tài
Tam quốc diễn nghĩa (Phan Kế Bính dịch, Bùi Kỷ hiệu đính)/Hồi 15
0
4193
205208
205151
2026-05-09T02:45:03Z
~2026-28014-86
20160
205208
wikitext
text/x-wiki
{{chất lượng vk|75%}}{{đầu đề
| tựa đề = [[../|Tam quốc diễn nghĩa]]
| tác giả = La Quán Trung
| dịch giả = Phan Kế Bính
| người hiệu đính = Bùi Kỷ
| phần = Hồi 15
| trước = [[../Hồi 14|Hồi 14]]
| sau = [[../Hồi 16|Hồi 16]]
| ghi chú =
}}
{{giữa|
HỒI THỨ MƯỜI LĂM
'''<poem>
Thái Sử-từ ham đánh Tiểu Bá-vương;
Tôn Bá-phù tợn giọt Nghiêm Bạch-hổ.
</poem>'''
}}
Cuối hồi trước, đang nói chuyện [[w:Trương Phi|Trương Phi]] rút gươm ra sắp tự vẫn, {{w|Lưu Bị}} trông thấy vội vàng bước lên giật lấy gươm, vứt xuống đất rồi nói rằng:
- Xưa có câu rằng: “Anh em như chân tay; vợ con như áo mặc”. Áo mặc rách còn dễ may; chân tay gãy chắp sao được? Ba anh em ta kết nghĩa với nhau ở vườn đào, đã thề cùng sống chết với nhau<ref>Xem [[../Hồi 1|Hồi thứ nhắt]].</ref>. Nay dù mất thành trì vợ con nữa, sao nỡ để anh em nửa đường chết đi cho đành. {{wikt|Phương chi}} thành trì không phải của ta; vợ con ta bị hãm ở trong thành, nhưng ta chắc Lã Bố không nỡ giết, cũng còn nghĩ kế cứu được. Hiền đệ nhầm một lúc, việc gì đã đến nỗi {{wikt|quyên sinh}}?
Lưu Bị nói xong rỏ nước mắt khóc. [[w:Quan Vũ|Quan]], [[w:Trương Phi|Trương]] cũng khóc cả.
{{w|Viên Thuật}} biết rằng {{w|Lã Bố}} đã cướp Từ-châu, sai người đến nói với Bố rằng: hễ Bố cùng giúp đánh Lưu Bị sẽ đưa cho năm vạn {{wikt|hộc}}<ref name="ReferenceA">Đơn vị đo cũ, một ''hộc'' tương đương với thể tích khoảng 20 {{w|lít}}.</ref> lương, năm trăm ngựa, một vạn {{wikt|lạng}}<ref>Đơn vị đo cũ, một ''lạng'' tương đương với khối lượng khoảng 37,8 {{w|gram}}.</ref> vừa vàng vừa bạc, một nghìn tấm vóc nhiễu.
Bố ưng ý lắm, sai ngay {{w|Cao Thuận}} lĩnh năm vạn quân đến đánh mé sau Lưu Bị. Lưu nghe tin ấy, nhân khi mưa dầm rút quân bỏ Vu-thai chạy, muốn về lấy Quảng-lăng.
Khi Cao Thuận đến nơi, Lưu Bị đã đi rồi. Thuận vào ra mắt Kỷ Linh, đòi những đồ Viên Thuật đã hứa cho. Linh nói:
- Ông cứ về. Để tôi vào nói với {{wikt|chúa công}} tôi.
Thuận từ giã Kỷ Linh, về thuật lại với Lã Bố. Bố còn đang hồ nghi, chợt có thư của Viên Thuật đưa đến, trong thư nói rằng:
“Cao Thuận tuy có đến giúp, nhưng Lưu Bị chưa trừ được. Đợi khi nào bắt được Lưu Bị, bấy giờ tôi sẽ đưa các đồ đã hứa đến cho ngài”.
Bố giận lắm, cho Viên Thuật là đồ {{wikt|thất tín}}, muốn khởi binh sang đánh, {{w|Trần Cung}} can rằng:
- Không nên! Viên Thuật giữ Thọ-xuân, binh nhiều lương rộng. Chớ nên khinh địch. Không bằng mời Lưu Bị về đóng ở Tiểu-bái để làm vây cánh cho ta. Về sau sai Lưu Bị làm {{wikt|tiên phong}}, trước đánh Viên Thuật sau đánh {{w|Viên Thiệu}} rồi có thể tung hoành thiên hạ được.
Bố nghe lời, sai người đem thư đi mời Lưu Bị.
Bấy giờ Lưu Bị đã kéo quân về đông, lấy đất Quảng-lăng, bị Viên Thuật vào cướp trại, quân lính hao hụt quá nửa, gặp sứ của Lã Bố đến, đưa thư mời về Tiểu-bái. Lưu mừng lắm. Quan, Trương nói:
- Lã Bố là đứa {{wikt|vô nghĩa}}, không nên tin.
Lưu Bị nói:
- Nó lấy bụng tử tế đãi ta, việc gì phải nghi?
[[Tập tin:Lady Gan Qing portrait.jpg|nhỏ|phải|Cam phu nhân]]
Ba anh em lại kéo quân về Từ-châu. Lã Bố sợ Lưu Bị còn nghi hoặc, trước hết sai người đưa trả lại {{wikt|gia quyến}}. {{w|Cam phu nhân}} và {{w|My phu nhân}} về gặp Lưu Bị, kể hết sự tình, nói rằng Lã Bố sai người giữ cửa nhà, cấm không cho ai được vào, lại thường thường sai {{wikt|thị thiếp}} đưa đồ ăn, thức dùng đến, không bao giờ phải thiếu thốn. Lưu Bị mới bảo Quan, Trương rằng:
- Ta đã biết Lã Bố tất không hại {{wikt|gia quyến}} ta!
Lưu Bị vào thành để tạ Lã Bố. Trương Phi không chịu theo vào, đem hai chị về Tiểu-bái trước.
Lưu Bị vào ra mắt lạy tạ Lã Bố. Bố nói:
- Tôi không phải muốn cướp thành. Bởi vì Trương Phi ở đây, hay say rượu giết người, tôi e rằng {{wikt|ngộ sự}}, nên tôi lại giữ hộ đấy thôi!
Lưu nói:
- Tôi vẫn muốn nhường anh đã lâu.
Bố giả dạng nhường lại cho Lưu Bị. Lưu nhất quyết không chịu, về đóng ở Tiểu-bái.
Quan, Trương trong bụng không bằng lòng.
Lưu Bị nói:
- Nhún mình yên phận, để đợi thời; không thể cưỡng nhau với mệnh được<ref>Ý nói ý trời đã sắp đặt thì không nên chống lại, tốt nhất là nhún nhường chờ thời cơ.</ref>!
Lã Bố thường thường sai người đưa lương ăn và vải lụa đến. Từ bây giờ hai bên lại {{wikt|hòa thuận}} với nhau.
Trong khi ấy thì Viên Thuật ở Thọ-xuân mở tiệc yến to, hội tướng sĩ lại ăn uống. Chợt có người báo rằng:
- {{w|Tôn Sách}} đi đánh [[wikt:thái thú|thái-thú]] Lư-giang là Lục Khang, đánh được đã về.
Thuật gọi Sách đến. Sách lạy ở dưới thềm. Thuật hỏi han chuyện trò xong rồi cho Sách ngồi hầu yến.
[[Tập tin:Sun_Ce_Portrait.jpg|phải|nhỏ|Tôn Sách. Tranh minh họa đời nhà Thanh.]]
Nguyên Tôn Sách từ khi [[w:Tôn Kiên|bố]] mất<ref>Xem cuối [[../Hồi 7|Hồi thứ bảy]].</ref>, về ở Giang-nam kính {{wikt|người hiền}}, tôn {{wikt|kẻ sĩ}}, sau, nhân {{w|Đào Khiêm}} cùng với cậu Sách, là {{wikt|thái thú}} Đang-dương tên là Ngô Cảnh không hòa với nhau, Sách mới đem mẹ và {{wikt|gia thuộc}} về Khúc-a, mình thì sang ở với Viên Thuật.
Thuật yêu Sách lắm, thường vẫn than rằng:
- Giá ta có được đứa con như [[w:Tôn Sách|Tôn lang]], chết cũng không ân hận gì nữa.
Thuật cho Sách làm hoài-nghĩa [[wikt:hiệu úy|hiệu-úy]], sai đem binh sang đánh Tổ Lang ở Kinh-huyện.
Sách đánh được.
Thuật thấy Sách giỏi, lại sai sang đánh Lục Khang cũng đánh được. Bấy giờ trở về.
Sách vào ăn yến. Khi cuộc yến đã tan, Sách về trại, nghĩ trong việc Thuật đãi mình khí ngạo bỉ một chút<ref>Ý là có ý khách khí, lịch sự.</ref>, trong bụng buồn bực, bèn lẩn đi bách bộ dưới bóng trăng ở ngoài sân. Nhớ đến sự ngày xưa, cha là {{w|Tôn Kiên}} thì anh hùng như thế mà minh thì lưu lạc thế này, bất giác hu hu cất tiếng khóc. Chợt có người ở ngoài đến cười to lên hỏi rằng:
- [[w:Tôn Sách|Bá-phù]] sao thế? Khi [[w:Tôn Kiên|Tôn công]] còn, việc gì cũng dùng đến ta, nay anh có việc gì không quyết, sao chẳng hỏi ta mà lại khóc thế?
Sách trông xem ai, thì là {{w|Chu Trị}}, người ở Đan-dương; nguyên là [[wikt:tùng sự|tùng-sự]] của Tôn Kiên ngày xưa.
Sách gạt nước mắt mời lên ngồi nói rằng:
- Tôi khóc là vì tôi giận tôi không nối được chí cha tôi ngày xưa.
Trị nói:
- Sao không tới với [[w:Viên Thuật|Viên Công-lộ]], mượn binh kéo sang Giang-đông, mượn tiếng là đi cứu Ngô Cảnh, nhưng sự thực là để mưu đồ nghiệp lớn, sao lại cứ chịu mãi ở dưới người ta?
Hai người đang bàn nhau, chợt lại có một người nữa ở đâu chạy vào nói rằng:
- Các ông bàn nhau việc gì tôi đã biết rồi, nay tôi có trăm quân {{wikt|tinh tráng}}, xin giúp Bá-phù một tay.
Sách nhìn xem ai thì là {{wikt|mưu sĩ}} Viên Thuật tên là {{w|Lã Phạm}}, người ở Nhữ-dương. Sách mừng lắm, mời cùng ngồi nói chuyện.
Lã Phạm nói:
- Tôi chỉ lo Viên Thuật không cho mượn quân.
Sách nói:
- Tôi có một vật báu để làm tin. Vật ấy là [[w:ngọc tỷ truyền quốc|truyền quốc ngọc-tỉ]] của cha tôi để lại cho.
Phạm nói:
- Công-lộ thèm được ngọc ấy đã lâu.
Hôm sau Sách vào ra mắt Viên Thuật, khóc nói rằng:
- Thù cha tôi chưa báo được, ngày nay cậu tôi là Ngô Cảnh lại bị [[wikt:thứ sử|thứ-sử]] Dương-châu là Lưu Do bức bách. Mẹ già và vợ con ở cả Khúc-a, e rằng sẽ bị hại. Vậy tôi xin mượn tướng quân vài nghìn {{wikt|hùng binh}} để sang sông cứu nạn, và để thăm nhà. Sợ {{wikt|minh công}} không tin, tôi xin đem ngọc-tỉ của cha tôi để lại, để làm tin.
Thuật thấy ngọc-tỉ vồ ngay lấy xem, mừng lắm nói rằng:
- Ta không phải cầu chi ngọc tỉ của ngươi, nhưng hãy tạm để đây, ta cho mượn ba nghìn binh, năm trăm ngựa; khi nào bình định rồi phải về ngay. Vả ngươi nay chức nhỏ ngôi thấp khó giữ được quyền lớn, ta cất cho ngươi lên làm triết-sung [[wikt:hiệu úy|hiệu-úy]], điển-khấu [[wikt:tướng quân|tướng-quân]].
Ngay ngày hôm ấy cho lĩnh quân đi.
Sách lạy tạ rồi dẫn quân mã, đem cả Chu Trị, Lã Phạm và tướng cũ của cha là {{w|Trình Phổ}}, {{w|Hoàng Cái}}, {{w|Hàn Đương}}, chọn ngày khởi binh.
Đi đến Lịch-dương, gặp một toán quân, có một người đi trước, dáng điệu {{wikt|phong lưu}}, {{wikt|nghi dung}} đẹp đẽ, trông thấy Tôn Sách, nhảy xuống ngựa vái một cái.
Sách nhìn xem ai, thì là {{w|Chu Du}}, {{w|biểu tự}} là Công-cẩn, người ở Thư-thành, quận Lư-giang.
[[Tập tin:ZhouYu.jpg|phải|nhỏ|Chu Du. Tranh minh họa đời nhà Thanh.]]
Vốn khi Tôn Kiên đánh {{w|Đổng Trác}}, Du đem gia quyến về ở Thư-thành. Du với Sách hai người cùng một tuổi, chơi với nhau rất thân, kết làm anh em. Sách hơn Du có vài tháng. Du thờ làm anh.
Chú Chu Du là Chu Thượng làm [[wikt:thái thú|thái-thú]] ở Đan-dương. Bữa ấy Du sang thăm chú, đi đến đấy gặp Tôn Sách.
Sách mừng lắm, đem sự tình kể với Du. Du nói:
- Tôn xin hết sức {{wikt|khuyển mã}}, để cùng anh mưu toan nghiệp lớn.
Sách nói:
- Ta nay được Du, việc lớn tất phải xong.
Rồi bảo Chu Trị, Lã Phạm cùng đến gặp Chu Du.
Du bảo Sách rằng:
- Anh nay muốn làm việc to, có biết Giang-đông có hai họ [[w:Trương (họ)|Trương]] không?
Sách hỏi:
- Ai vậy?
Du nói:
- Một người ở Bình-thành, tên là {{w|Trương Chiêu}}, tự là Tử-bố; một người ở Quảng-lăng, tên là [[w:Trương Hoành (Đông Ngô)|Trương Hoành]], tự là Tử-cương. Hai người ấy đều có tài ngang trời dọc đất; nhân tránh loạn đến ở đấy, sao anh không đón mời hai người ấy.
[[Tập tin:ZhangZhao.jpg|nhỏ|phải|Trương Chiêu. Tranh minh họa đời nhà Thanh.]]
Sách sai người đem đồ lễ đến mời Trương Chiêu, Trương Hoành. Hai người đều từ chối không đến. Sách phải {{wikt|thân}} đến tận nơi, cùng hai người nói chuyện. Sách rất lấy làm bằng lòng cố mời đi mời lại mãi, hai người mới chịu vâng lời. Sách cho Trương Chiêu làm [[wikt:trưởng sử|trưởng-sử]], kiêm chức [[wikt:phủ quân|phủ-quân]] [[wikt:trung lang tướng|trung-lang-tướng]]; Trương Hoành làm [[wikt:tham mưu|tham-mưu]], chánh-nghị [[wikt:hiệu úy|hiệu-úy]].
Cùng nhau bàn mưu sang đánh Lưu Do.
Lưu Do, tự là Chính-lý, cũng là {{wikt|tôn thân}} nhà Hán, cháu quan [[wikt:thái úy|thái-úy]] Lưu Sủng, em quan [[wikt:thứ sử|thứ-sử]] Duyện-châu Lưu Đại. Trước làm thứ-sử Dương-châu, đóng ở Thọ-xuân, sau bị Viên Thuật đuổi sang Giang-đông, cho nên đến Khúc-a ở.
Bấy giờ Lưu Do nghe thấy binh Tôn Sách đến, vội vàng họp các tướng để bàn.
{{wikt|Bộ tướng}} là Trương Anh nói:
- Tôi xin lĩnh một cánh quân, đóng đồn Ngưu-chử, quân giặc dẫu có trăm vạn cũng không dám đến gần.
Nói chưa dứt lời, dưới trướng lại có một người kêu to lên rằng:
- Tôi xin làm {{wikt|tiền bộ}} {{wikt|tiên phong}}!
Chúng tướng nhìn xem ai, thì là người ở Đông-lai, tên [[w:Thái Sử Từ|Thái Sử-từ]].
Từ, tự khi giải được vây Bắc-hải cho {{w|Khổng Dung}}, sang với Lưu Do. Do giữ lại ở dưới trướng.
Do bảo:
- Ngươi còn ít tuổi, chưa nên làm [[wikt:đại tướng|đại-tướng]], hãy nên ở {{wikt|tả hữu}} ta để nghe mệnh lệnh.
Từ không bằng lòng lùi ra.
Trương Anh lĩnh quân đến Ngưu-chử, chứa mười vạn hộc<ref name="ReferenceA"/> lương ở Để-các.
Tôn Sách dẫn quân đến. Trương Anh ra địch. Hai bên hội quân ở trên bãi sông Ngưu-chử.
Trương Anh chửi mắng, Hoàng Cái ra đánh nhau với Trương Anh, chưa được vài hợp, bỗng thấy trong quân Trương Anh bối rối, rồi thấy nói: “Trong trại có người phóng hỏa!”.
Anh vội rút quân về. Tôn Sách thừa thế đánh {{wikt|dấn}}. Trương Anh thế cùng phải bỏ Ngưu-chử chạy trốn vào trong núi sâu.
[[Tập tin:Zhou Tai Qing illustration.jpg|nhỏ|phải|Chu Thái]]
Người phóng hỏa ở trong trại nguyên là hai viên {{wikt|kiện tướng}}. Một là {{w|Tưởng Khâm}}, tự là Công-địch, người ở Thọ-xuân, một là {{w|Chu Thái}} tự là Ấu-bình, người ở Cửu-giang. Hai người gặp phải thời loạn, tụ quân trong [[w:Trường Giang|sông Dương-tử]], cướp bóc kiếm ăn; vốn nghe tiếng Tôn Sách là người {{wikt|hào kiệt}} ở Giang-đông, hay cầu {{wikt|người hiền}}, {{wikt|vời}} {{wikt|kẻ sĩ}}, cho nên dẫn {{wikt|đồ đảng}} hơn ba trăm người đến theo. Sách mừng lắm, dùng làm trướng-tiền [[wikt:hiệu úy|hiệu-úy]], thu được cả tiền lương khí giới ở Ngưu-chử và ở Để-các, lại thêm được hơn bốn nghìn quân hàng, liền tiến binh lên đóng ở Thần-đình.
Trương Anh thua trở về vào ra mắt Lưu Do. Do giận muốn đem chém, lại có các mưu sĩ là Trích Dung và Tiết Lễ can mãi mới tha, sai Trương Anh đem quân đóng ở thành Linh-lăng để chống giặc, Do tự lĩnh quân ra mé nam núi Thần-đình cắm trại.
Tôn Sách đóng ở phía bắc núi ấy.
Hôm sau Sách gọi người ở đấy hỏi rằng:
- Ở gần đây có miếu nào thờ vua [[w:Hán Quang Vũ|Quang Vũ]] chăng?
Người ấy thưa:
- Có miếu ở trên đỉnh núi.
Sách nói:
- Đêm ta {{wikt|chiêm bao}} thấy vua Quang Vũ gọi ta vào {{wikt|tương kiến}}. Ta định lên miếu ấy cầu.
[[wikt:trưởng sử|Trưởng-sử]] là {{w|Trương Chiêu}} can rằng:
- Không nên đi! Mé nam núi này có trại Lưu Do. Ngộ nó có {{wikt|phục binh}} làm thế nào?
Sách nói:
- Ta đã có thần thánh phù hộ, việc chi còn phải sợ?
Nói xong liền mặc áo giáp, cầm giáo, lên ngựa, rồi đem bọn Trình Phổ, Hoàng Cái, Hàn Đương, Tưởng Khâm và Chu Thái cả thảy 13 người cùng cưỡi ngựa lên núi. Đến miếu, xuống ngựa, vào thắp hương lễ bái, Sách quỳ xuống khấn rằng:
- Tôi là Tôn Sách. Xin nguyện rằng nếu lập được nghiệp lớn ở đất Giang-đông, khôi phục lại được {{wikt|cơ đồ}} của cha tôi ngày xưa, tôi xin sửa sang đình miếu bốn mùa lễ bái.
Sách khấn vái xong đi ra miếu, lên ngựa ngoảnh lại bảo chúng tướng:
- Ta muốn qua bên kia núi, dòm xem dinh trại Lưu Do đóng ra làm sao?
Các tướng ai cũng ngăn:
- Không nên!
Sách không nghe, cứ việc đi. Các tướng cũng phải đi theo. Đến phía nam núi, đứng trên trông xuống rừng rú và trại Lưu Do đóng. Có quân canh đường, chạy về báo với Lưu Do. Do nói:
- Đây hẳn là mẹo Tôn Sách đến {{wikt|dử}} mình đây, không nên ra đánh.
Thái Sử-từ nhảy lên nói rằng:
- Lúc này không bắt Tôn Sách thì còn đợi đến lúc nào?
Nói xong không đợi lệnh Lưu Do, tự mặc ngay áo giáp, lên ngựa, ra ngoài trại, hô lên:
- Ai có gan thì theo ta!
Các tướng không ai nhúc nhích. Chỉ có một {{wikt|tiểu tướng}} bước ra nói:
- Thái Sử-từ thế mới gọi là tướng giỏi. Ta nên đi giúp một tay.
Nói rồi lên ngựa đi theo Thái Sử-từ. Các tướng đều tủm tỉm cười.
Tôn Sách ngắm xem độ nửa giờ mới quay ngựa trở về. Vừa đi qua được đỉnh núi nghe thấy đằng sau có người thét:
- Tôn Sách đừng chạy nữa!
Sách ngoảnh lại thấy hai tướng cưỡi ngựa chạy đến. Sách đem 12 tướng sắp một hàng, còn mình cầm ngang ngọn giáo, cưỡi ngựa đứng đợi ở dưới núi.
Thái Sử-từ hỏi to:
- Người nào là Tôn Sách?
Sách hỏi:
- Mày là thằng nào?
Từ đáp:
- Tao là Thái Sử-từ ở Đông-lai, tao lại đây chỉ cốt để bắt Tôn Sách.
Sách cười nói:
- Đây! Tôn Sách đây! Cho cả hai thằng chúng bay lại đánh một mình tao, tao không sợ. Nếu tao sợ, sao gọi là Tôn Bá-phù?
Từ nói:
- Tất cả chúng mày đều đến, tao cũng không sợ.
Nói xong thúc ngựa múa thương vào đánh Tôn Sách. Sách vác giáo lại địch. Hai ngựa giao nhau, đánh được hơn năm mươi hợp, được thua chưa phân, lũ Trình Phổ đứng ngoài khen thầm rằng giỏi. Từ thấy Sách đánh giáo không hở miếng nào, giả cách thua chạy để dử cho Tôn Sách đuổi ra xa. Từ không đi đường cũ lên núi, lại rẽ về sau núi mà chạy, Sách vừa đuổi vừa thét to:
- Chạy không phải là {{wikt|hảo hán}}!
Từ trong bụng nghĩ thầm:
- Nó có 12 người đi theo ta chỉ {{wikt|trọi}} một mình. {{wikt|Ví dù}} bắt được nó, cũng bị chúng cướp mất. Phải dử cho nó đi một đường nữa, để cho chúng không biết đường nào mà tìm, bấy giờ ta sẽ ra tay.
Bởi thế vừa đánh vừa lùi. Sách cũng cứ đuổi, đuổi nhau mãi đến Bình-xuyên. Bấy giờ Từ mới quay lại đánh. Đánh nhau được 50 hợp nữa, Sách phóng một ngọn giáo lại. Từ tránh ngay được, lại trở tay bắt được giáo. Từ lại phóng giáo lại, Sách cũng tránh được và giơ tay bắt lấy giáo, rồi nắm chặt lấy. Từ chạy lại giằng về, hai người kéo co nhau rồi cùng nhảy cả xuống ngựa. Để ngựa chạy đi đâu không biết nữa.
Lôi kéo nhau chán rồi hai người cùng buông cả vũ khí ra, túm lấy nhau mà đánh. Hai bên, bên nào áo chiến cũng rách tan nát. Sách nhanh tay vớ được cái kích ngắn gài ở lưng Từ; Từ giật ngay được mũ [[wikt:đâu mâu|đâu-mâu]] của Sách. Sách cầm kích đâm Từ; Từ lấy mũ che đỡ.
Giữa lúc ấy có tiếng reo ầm ầm kéo đến, quân tiếp ứng của Lưu Do, ước hơn nghìn người.
Sách đã lấy làm nguy, may đâu bọn Trình Phổ 12 tướng cưỡi ngựa cũng vừa tìm được đến.
Hai người bấy giờ mới buông nhau ra.
Từ lên một con ngựa khác rồi cầm cây thương lên .
Ngựa của Tôn Sách Trình Phổ bắt được, Sách cũng nhặt lấy giáo rồi lên ngựa.
Một nghìn quân Lưu Do cùng 12 tướng Tôn Sách hai bên đánh nhau. Đánh lần quanh mãi đến tận dưới núi Thần-đình.
Bấy giờ lại thấy tiếng reo, Chu Du kéo quân đến. Lưu Do lại dẫn đại quân xuống núi. Khi ấy trời đã vàng vàng tối, tự dưng nổi cơn mưa gió, hai bên cùng thu quân về.
Hôm sau, Tôn Sách dẫn quân đến trước trại Lưu Do. Do cũng đem quân ra đón. Khi hai bên bầy trận rồi, Tôn Sách lấy cái kích nhỏ rút được của Từ hôm trước, đem buộc ở đầu giáo, cầm ra giễu ở trước trận, rồi sai quân hô to lên rằng:
- Giá Thái Sử-từ không chạy mau chân thì đã bị kích này đâm chết.
Từ cũng đem mũ đâu-mâu của Sách ra trước trận, sai quân hô lên rằng:
- Đầu Tôn Sách đã ở đây rồi!
Hai bên nhạo báng lẫn nhau, reo ầm cả lên. Bên cậy khỏe, bên khoe tài. Thái Sử-từ phóng ngựa ra định cùng Tôn Sách quyết {{wikt|thắng phụ}}.
Sách sắp sửa ra, Trình Phổ nói:
- Chúa công {{wikt|lọ}} là phải khó nhọc. Tôi xin ra bắt nó.
Trình Phổ ra trận. Từ nói:
- Mày không đáng địch với tao. Về gọi Tôn Sách ra đây!
Trình Phổ tức lắm, vác ngọn mâu xông vào đánh Từ. Hai ngựa giao đấu được hơn 30 hợp, bỗng thấy Lưu Do khua chiêng thu quân.
Từ hỏi Lưu Do:
- Tôi đã sắp bắt được tướng giặc sao lại thu quân về?
Do nói:
- Có người báo rằng: Chu Du đã đem quân đánh úp lấy Khúc-a, vì có người ở Lư-giang, tên là [[w:Trần Vũ (Đông Ngô)|Trần Vũ]] tiếp ứng cho nó vào thành. Cơ nghiệp nhà ta đã mất, không nên ở mãi đây; phải kíp sang Mạt-lăng, hội cả quân mã của Tiết Lễ, Trích Dung lại để tiếp ứng.
Thái Sử-từ theo Lưu Do lui quân. Tôn Sách không đuổi cũng thu quân về. Trương Chiêu nói:
- Bên nó bị Chu Du lừa lấy Khúc-a, không dám ham đánh, đêm nay ta nhân thế nên đến cướp trại.
Sách ưng ý, đang đêm chia quân làm năm đường, kéo đến lấy trại Lưu Do. Quân Do thua to, chạy tán loạn cả, Thái Sử-từ một mình không chống nổi, dẫn hơn mười quân kỵ ngay đêm hôm ấy chạy sang Kinh-huyện.
Tôn Sách lại vừa được thêm một tay phụ-tá nữa là [[w:Trần Vũ (Đông Ngô)|Trần Vũ]], biểu tự Tử-liệt. Vũ mình cao bảy thước<ref>Một ''thước'' vào thời nhà Hán dài khoảng 23,1 cm. Bảy thước là khoảng 1,61 m.</ref>, mặt vàng, con ngươi đỏ, hình dung cổ quái. Sách yêu lắm cho làm [[wikt:hiệu úy|hiệu-úy]]; sai đi tiên phong đánh Tiết Lễ. Vũ dẫn hơn mười kỵ mã, xông vào trong trận chém hơn năm mươi đầu giặc. Tiết Lễ thấy vậy đóng chặt cửa thành không dám ra nữa.
Sách đang đánh phá thành, có người báo rằng:
- Lưu Do hội với Trích Dung sang lấy Ngưu-chử.
Sách giận lắm, tự để đại-quân kéo về Ngưu-chử. Lưu Do, Trích Dung hai người cùng cưỡi ngựa ra đón đánh. Tôn Sách nói:
- Tao nay đã đến đây sao chúng bay không hàng ngay đi?
Ở sau Lưu Do bỗng có một người vác giáo cưỡi ngựa ra, là bộ tướng tên là Vu Mi, cùng Sách đánh nhau, chưa được ba hợp, bị Sách bắt sống rồi quay ngựa trở về trận. Tướng Lưu Do là Phàn Năng, thấy Vu Mi bị bắt liền vác giáo đuổi theo, ngọn giáo gần đâm đến sau lưng Tôn Sách, quân Sách thấy vậy mới kêu to lên rằng:
- Sau lưng có người đâm trộm!
Sách quay đầu lại, thấy Phàn Năng đã đến gần, quát to một tiếng, như tiếng sét. Phàn Năng khiếp đảm, ngã quay xuống vỡ đầu ra chết. Sách về đến cửa cờ, đem Vu Mi bỏ xuống đất, thì ra Vu Mi bị cắp ở nách đã chết kẹp từ bao giờ.
Trong một lúc, cắp chết một tướng, quát chết một tướng, từ đấy ai cũng gọi là Tiểu bá Vương ({{w|Hạng Võ}} ngày xưa gọi là Bá Vương).
Lưu Do thua to. Quân sĩ hàng Sách quá nửa. Sách lại chém được hơn một vạn cấp.
Do và Trích Dung chạy sang Dự-chương, đi theo {{w|Lưu Biểu}}.
Tôn Sách đem quân về lại đánh Mạt-lăng. Đến cạnh bờ hào, Sách đứng chiêu dụ Tiết Lễ hàng, chợt có một mũi tên ở trên thành bắn xuống trúng ngay vào đùi trái Tôn Sách. Tôn Sách ngã ngựa. Các tướng vội vàng đến cứu, nhắc Sách dậy đem về trại nhổ tên ra, lấy thuốc dấu dịt vào khỏi.
Sách nhân thể cho quân đi nói phao lên rằng bị tên bắn chết. Cả cánh quân làm lễ {{wikt|cử ai}}, nhổ trại kéo về.
Tiết Lễ tưởng Tôn Sách chết thật, đêm hôm ấy liền khởi cả quân trong thành cùng với [[wikt:kiêu tướng|kiêu-tướng]] là Trương Anh, Trần Hoành, kéo ra thành đuổi đánh. Bỗng đâu quân phục bốn mặt trổ ra, Tôn Sách đứng đầu đi trước gọi to lên rằng:
- Tôn-lang ở đây mà!
Quân giặc trông thấy mất vía vứt cả gươm giáo, phục xuống đất lạy. Sách truyền lệnh không được giết một người nào.
Trương Anh quay ngựa chạy về bị Trần Vũ đâm chết, Trần Hoành bị Tưởng Khâm bắn chết; Tiết Lễ chết ở trong đám loạn quân.
Sách vào Mạt-lăng, {{wikt|phủ dụ}} cho dân yên {{wikt|nghiệp}} rồi đem binh sang Kinh-huyện để bắt Thái Sử-từ.
Thái Sử-từ chiêu được hai nghìn quân [[wikt:tinh tráng|tinh-tráng]] và quân cũ của mình, toan lại báo thù cho Lưu Do.
Tôn Sách với Chu Du bàn nhau kế bắt sống Thái Sử-từ.
Chu Du truyền lệnh cho quân sĩ chỉ vây ba mặt đánh huyện, để chừa một mặt cửa đông cho Từ chạy. Cách huyện 25 dặm<ref>Một ''dặm'' vào thời nhà Hán dài khoảng 415,8 m. 25 dặm là khoảng 10 km.</ref>, phục binh ba nơi. Từ ra khỏi thành chạy được đến đấy, người mệt, ngựa mỏi, tất nhiên bị bắt.
Nguyên những quân của Thái Sử-từ dụ được quá nửa là người ở rừng núi, chưa biết kỷ luật nhà binh. Vả thành Kinh-huyện lại không được cao. Đêm hôm ấy Tôn Sách sai Trần Vũ, mặc áo ngắn cầm đao, trèo trước lên mặt thành đốt lửa. Từ thấy trên thành lửa cháy, lên ngựa chạy ra cửa đông. Tôn Sách đem quân lại đuổi, đuổi đến ba mươi dặm<ref>30 dặm là khoảng 12,5 km.</ref> thì thôi. Từ chạy được năm mươi dặm<ref>50 dặm là khoảng 20 km.</ref>, người ngựa đều đã mỏi mệt, giữa lúc ấy trong đám cỏ lau bên đường có tiếng reo nổi lên. Từ vội chạy, hai bên đường chằng chịt những dây, ngựa vướng cẳng ngã gục xuống. Thái Sử-từ bị bắt sống, giải về trại Tôn Sách.
[[Tập tin:Phragmites_australis_Schilfrohr.jpg|nhỏ|phải|Cây lau sậy.]]
Lúc quân lính sắp giải Từ đến nơi, Sách biết trước ra tận cửa dinh, quát đuổi quân lính, tự ra cởi trói, rồi đem áo [[wikt:cẩm bào|cẩm-bào]] mặc cho Từ, mời vào trong trại nói rằng:
[[Tập tin:Taishi_Ci_Qing_illustration.jpg|nhỏ|phải|Thái Sử-từ. Tranh minh họa đời nhà Thanh.]]
- Ta biết [[w:Thái Sử Từ|Tử-nghĩa]] là một đấng [[wikt:trượng phu|trượng-phu]]. Bởi Lưu Do đứa ngu xuẩn, không biết dùng Tử-nghĩa làm đại-tướng cho nên đến nỗi có trận thua này.
Từ thấy Sách đối đãi mình tử tế, xin xuống hàng. Sách cầm lấy tay Từ cười nói rằng:
- Khi đánh nhau ở Thần-đình, giá thử ông bắt được tôi, thì có hại nhau không?
Từ cũng cười đáp rằng:
- Cũng chưa biết chừng!
Sách cười ầm lên, mời vào trướng, mời lên ngồi trên, sai mở tiệc yến khoản đãi. Từ đứng dậy nói rằng:
- [[w:Lưu Do|Lưu-quân]] mới thua, lòng quân tan rã, tôi xin về để thu nhặt dư chúng, để giúp minh công. Không biết minh công có tin không?
Sách đứng dậy tạ mà nói rằng:
- Bụng tôi vẫn ước như thế, nay xin hẹn với ông bây giờ ông về bên ấy, trưa mai tôi xin đợi ông ở đây.
Từ vâng lời rồi đi.
Các tướng ngạc nhiên nói rằng:
- Thái Sử-từ đi chuyến này tất không trở lại đâu!
Sách nói:
- Từ là người {{wikt|tín nghĩa}} không trái ước với ta.
Các tướng chẳng ai tin. Hôm sau cắm một {{w|cây nêu}} để đo bóng mặt trời ở trước cửa trại, rồi các tướng cùng xúm cả chung quanh để đợi giờ ngọ<ref>Trung Quốc xưa chia một ngày thành 12 giờ với mỗi giờ bằng gần 2 tiếng ngày nay, đặt theo tên 12 con giáp. Giờ ngọ là từ 12 đến 14 giờ, tức là lúc giữa trưa.</ref>. Cây nêu vừa đứng bóng thì thấy Thái Sử-từ dẫn hơn một nghìn quân đến.
{{wikt|Chúng}} đều chịu Tôn Sách là biết người.
Tôn Sách tụ được vài vạn quân, bình trị được Giang-đông, vỗ yên dân chúng, người kéo về theo vô số. Dân Giang-đông ai cũng gọi Sách là Tôn-lang.
Quân Tôn-lang đi đến đâu, người sợ đến đấy, thế mà khi Sách đến nơi, tịnh không cho một người nào cướp bóc của dân, cho đến gà chó cũng không kinh động. Nhân dân thấy thế ai cũng mừng, đem trâu ngựa đến trại để mừng. Sách lại đem vàng, đem lụa ra trả lại. Tiếng vui mừng đầy khắp ngoài đường. Phàm những quân cũ của Lưu Do, ai muốn theo thì cho theo, ai không muốn theo thì cấp thưởng cho về làm ruộng.
Dân Giang-nam ai cũng khen Tôn Sách là người nhân đức. Bởi vậy quân thế mỗi ngày một thịnh.
Bấy giờ Sách mới rước mẹ, chú và các em cùng về Khúc-a; sai em là {{w|Tôn Quyền}} cùng với {{w|Chu Thái}} giữ Tuyên-thành. Sách thì lĩnh binh sang Nam để lấy Ngô-quận.
Bấy giờ [[w:Nghiêm Bạch Hổ|Nghiêm Bạch-hổ]], tự xưng là Đông Ngô Đức-vương, giữ ở Ngô-quận. Bạch-hổ sai bộ tướng giữ Ô-trình và Gia-hưng. Bấy giờ nghe tin quân Tôn Sách đến, Bạch-hổ sai em là Nghiêm Dư đem quân ra.
Hai bên gặp nhau ở Phong-kiều. Dư vác đao cưỡi ngựa đứng trên cầu. Sách muốn ra địch, Trương Hoành can rằng:
- Chủ tướng là vận mệnh của {{wikt|ba quân}}, ai cũng trông cậy cả vào, không nên khinh địch với quân {{wikt|tiểu}}-{{wikt|khấu}}. Xin tướng quân tự cẩn trọng.
Sách tạ nói rằng:
- Lời tiên sinh nói như vàng đá<ref>Ý nói cứng và mạnh, cứng rắn.</ref>. Nhưng nếu tôi không chịu xông vào mũi tên hòn đạn thì tướng sĩ ai chịu dùng sức!
Bèn sai Hàn Đương cưỡi ngựa ra.
Khi Hàn Đương đi lên đến cầu, đã thấy Tưởng Khâm, Trần Vũ bơi thuyền nhỏ theo bờ sông, lượn sang được bên kia cầu, bắn tên tua tủa lên quân đứng trên bờ, hai người nhảy lên đánh giết, quân Nghiêm Dư phải lùi chạy. Hàn Đương kéo quân thẳng đến cửa thành. Giặc chạy cả vào trong thành. Sách chia quân đường thủy đường {{wikt|lục}} cùng tiến, vây bọc cả lấy Ngô-thành. Vây luôn ba ngày không ai dám ra đánh.
Sách dẫn quân đến dưới cửa thành để chiêu dụ. Trên thành, một viên [[wikt:tì tướng|tỳ tướng]], tay trái cầm chắc thanh ván đỡ tên, tay phải trỏ xuống chửi mắng.
Thái Sử-từ ngồi trên ngựa giương cung đặt tên xong rồi ngoảnh lại bảo chư tướng rằng:
- Xem ta bắn trúng vào tay trái thằng kia nhé!
Nói chưa dứt lời, dây cung tách một tiếng, quả nhiên trúng giữa bàn tay trái tên tướng trên thành, lại {{wikt|suốt}} qua tay cắm vững vào tấm ván.
Người trên thành dưới thành ai cũng reo ồ lên.
{{wikt|Chúng}} vội vàng cứu tướng ấy đem xuống thành. Bạch-hổ trông thấy thất kinh nói rằng:
- Quân nó có người tài như thế, ta địch sao được?
Bàn nhau muốn cầu hòa.
Hôm sau Bạch-hổ sai Nghiêm Dư ra thành vào ra mắt Tôn Sách. Sách mời Dư vào trướng uống rượu. Rượu đã say, Sách hỏi Dư:
- Ý {{wikt|lệnh huynh}} muốn thế nào?
Dư nói:
- Muốn cùng tướng quân chia đôi Giang-đông.
Sách nổi giận mắng rằng:
- Đàn chuột nhắt lại đòi ngang vai với ta à!
Mắng rồi thét đem Nghiêm Dư ra chém.
Dư rút gươm đứng dậy, Sách cầm thanh gươm ném ra, trúng ngay cổ Nghiêm Dư ngã xuống, cắt ngay lấy đầu, sai người đưa vào thành.
Bạch-hổ biết chừng không địch nổi, bỏ thành chạy. Sách kéo quân đuổi theo. Hoàng Cái đánh lấy được Gia-hưng; Thái Sử-từ đánh lấy được Ô-trình, mấy châu đều {{wikt|bình định}} cả. Bạch-hổ chạy về Dư-hàng, cướp bóc ở dọc đường, lại bị người {{wikt|thổ dân}} ở đấy tên là {{w|Lăng Tháo}} đem người làng ra đánh, Bạch-hổ phải thu quân về Cối-kê.
Hai bố con Lăng Tháo lại đi đón Tôn Sách. Sách cho làm [[wikt:tòng chinh|tông-trinh]] [[wikt:hiệu úy|hiệu-úy]], cũng dẫn binh sang qua sông. Bạch-hổ tụ quân, dàn khắp ở bến Tây-tân. Trình Phổ đánh một trận, đuổi mãi đến thành Cối-kê.
{{wikt|Thái thú}} Cối-kê tên là {{w|Vương Lãng}}, muốn đem binh ra cứu Bạch-hổ, có người can rằng:
- Không nên cứu, Tôn Sách dùng quân nhân nghĩa; Bạch-hổ là một tướng bạo ngược. Nên bắt Bạch-hổ đem dâng Tôn Sách.
Lãng nhìn xem ai bàn kế ấy; thì là {{w|Ngu Phiên}}, tự là Trọng-tường, người ở Cối-kê, hiện đương làm [[wikt:quận lại|quận-lại]]. Lãng giận mắng Phiên. Phiên thở dài trở ra.
Lãng đem binh hội với Bạch-hổ, dàn quân ở cánh đồng Sơn-âm; hai bên đối trận. Tôn Sách cưỡi ngựa ra bảo Vương Lãng rằng:
- Ta cất quân {{wikt|nhân nghĩa}} đi dẹp Tích-giang, sao mày dám tùng đảng với giặc?
Lãng mắng rằng:
- Bụng mày tham không có chừng, đã được Ngô-quận rồi lại còn muốn chiếm nốt bờ cõi ta. Nay ta báo thù cho họ Nghiêm cho mày biết tay!
Tôn Sách giận lắm, sắp ra đánh nhau thì Thái Sử-từ ra lúc nào rồi. Vương Lãng múa đao tế ngựa, đánh nhau với Từ chưa được vài hợp, tướng Lãng là Chu Hân nhảy ra đánh đỡ. Bên này {{w|Hoàng Cái}} cũng tế ngựa ra tiếp ứng, đánh với Chu Hân.
Hai bên trống đánh vang lừng, đánh nhau lộn bậy. Tự nhiên thấy đằng sau trận Vương Lãng bối rối. Một toán quân đâu từ sau lưng đánh lại. Lãng thất kinh kíp quay ngựa trở về.
Quân đánh tập hậu ấy là Chu Du và Trình Phổ, trong khi hai bên đánh nhau, đi tắt lẻn mặt sau.
Đằng trước đằng sau đánh dập lại. Lãng quân ít không chống xuể, cùng với Bạch-hổ, Chu Hân cố đánh để mở lấy một đường máu chạy vào thành, buông cầu xuống, đóng vững cửa thành lại.
Đại quân Tôn Sách thừa kế, xấn đến mãi dưới thành, chia quân ra bốn cửa. Vương Lãng ở trong thành thấy Sách đánh kíp lắm, lại muốn kéo quân ra quyết đánh một trận sống chết cũng đành. Bạch-hổ can rằng:
- Binh thế Tôn Sách to lắm, {{wikt|túc hạ}} chỉ nên thành cao hào sâu cho vững. Không đầy một tháng, quân kia hết lương tất phải chạy. Bấy giờ ta thừa thế ra đuổi, có thể chẳng phải đánh cũng phá tan được.
Lãng nghe kế ấy, cứ vững thành không ra.
Tôn Sách đánh luôn mấy hôm không phá được thành bèn cùng chư tướng bàn mưu kế. Tôn Tĩnh nói:
- Vương Lãng cậy hiểm giữ thành, khó phá ngay được. Tiền lương đất Cối-kê quá nửa chứa ở Tra-độc, đem binh giữ lấy Tra-độc trước. Trong binh pháp có nói rằng: “đánh chỗ {{wikt|vô bị}}, ra nơi không ngờ<ref>Đây là câu thứ 24, Chương 1 - Thiên Kế trong [[Binh pháp Tôn Tử]], nguyên văn: ''Công kỳ vô bị, xuất kỳ bất ý'' (攻其無備出其不意).</ref>” là thế đó.
Sách mừng nói:
- Mẹo hay của chú đủ phá được giặc.
Liền hạ lệnh sai các cửa thành đốt lửa giả cắm cờ hiệu để làm nghi binh, rồi đêm hôm ấy rút vây, kéo quân sang mặt nam.
Chu Du hiến một kế rằng:
- Chúa công kéo cả quân, Vương Lãng tất ra thành đuổi theo. Nếu nó ra ta nên dụng {{wikt|kỳ binh}} mà đánh.
Sách nói:
- Ta đã sắp sẵn cả rồi. Lấy thành chỉ nội đêm nay.
Bèn hạ lệnh cho quân mã đi.
Vương Lãng nghe tin báo Tôn Sách rút quân mã đi, liền dẫn quân lên Địch-lâu trông xem, thấy dưới thành khói lửa vẫn ngùn ngụt, {{wikt|tinh kỳ}} đâu vẫn đấy, trong bụng còn nghi hoặc, Chu Hân nói:
- Tôn Sách chạy rồi, bày ra mẹo này để đánh lừa ta đấy thôi, nên đem binh ra đuổi đánh.
Nghiêm Bạch-hổ nói:
- Tôn Sách chuyến này đi, dễ thường định đến Tra-độc. Tôi xin đem bộ binh đuổi theo.
Lãng nói:
- Tra-độc là chỗ ta chứa lương, cần phải đề phòng cẩn thận. Người đi trước, ta theo sau để tiếp ứng.
Bạch-hổ lĩnh năm nghìn quân ra thành đuổi theo.
Bấy giờ mới canh một<ref>Ngày xưa một đêm được chia làm 5 canh gác, cứ qua mỗi canh lại có người đánh trống hoặc kẻng để báo hiệu, từ đó có đơn vị thời gian [[wikt:canh|canh]] vào ban đêm. Canh một là khoảng từ 7 đến 9 giờ tối.</ref>. Đi khỏi thành được hơn hai mươi dặm<ref>Hai mươi dặm là khoảng 8.300 km.</ref>, bỗng đâu trong rừng rậm, có một tiếng trống nổi, rồi lửa đuốc sáng rực cả lên. Bạch-hổ thất kinh, liền quay ngựa trở lại, thì có một tướng chắn ngang đường.
Chính là Tôn Sách.
Chu Hân múa đao lại đánh, bị Sách đâm một mũi giáo chết. Quân thấy thế xuống hàng cả. Bạch-hổ cố chết mở một đường, rồi chạy về Dư-hàng.
Vương Lãng nghe tiền quân đã thua, không dám vào thành, dẫn bộ binh chạy ra góc bể đi trốn.
Tôn Sách thu quân trở lại, thừa thế lấy ngay thành trì, vỗ yên nhân dân.
Được mấy hôm có người mang đầu Bạch-hổ đến dâng. Tôn Sách nhìn người ấy, mình cao tám thước<ref>Tám thước là khoảng 1,85 m.</ref>, mặt vuông, mồm rộng; hỏi tên họ là gì, thì người ấy xưng tên là {{w|Đổng Tập}}, biểu tự Nguyên-đại, người ở Cối-kê.
Sách mừng lắm cho làm biệt-bộ [[wikt:tư mã|tư-mã]].
Từ đó xứ đông bình định được cả. Sách sai chú là Tôn Tĩnh giữ ở đấy; còn mình thì thu quân về Giang-đông.
Em Sách là {{w|Tôn Quyền}} cùng với {{w|Chu Thái}} giữ ở Tuyên-thành. Chợt có giặc núi bốn mặt kéo đến. Bấy giờ đêm đã khuya, không kịp chống cự. Thái ôm Quyền lên ngựa để chạy. Giặc vác dao xông vào chém. Thái cởi trần ra, xuống ngựa đi bộ, cầm dao đánh nhau với giặc, một lúc giết luôn được hơn mười đứa. Sau có một tên giặc, tế ngựa vác giáo nhảy xổ vào để giết Chu Thái, Thái nắm ngay được giáo, rẩy giặc ngã xuống, cướp được ngựa giặc, đánh riết mở được đường ra, cứu được Tôn Quyền.
Giặc thấy vậy chạy cả. Thái bị cả thảy mười hai vết thương nặng, sưng lên, gần chết. Sách nghe tin lo lắm. Đổng Tập nói:
- Tôi đã nhiều phen đánh nhau với giặc bể, bị thương, may có một người {{wikt|quận lại}} ở Cối-kê, tên là {{w|Ngu Phiên}} tiến cử một thầy thuốc, chữa cho chỉ nửa tháng là khỏi.
Sách hỏi:
- Ngu Phiên có phải là Ngu Trọng không?
Tập thưa:
- Phải.
Sách nói:
- Người ấy là {{wikt|hiền sĩ}}, ta nên dùng.
Liền sai Trương Chiêu, Đổng Tập đến mời Ngu Phiên. Phiên đến. Sách thết đãi cực hậu, cho làm [[wikt:công tào|công-tào]]. Nhân nói chuyện thày thuốc, Phiên nói rằng:
- Người ấy là người ở Tiêu-quận, nước Bái, tên là {{w|Hoa Đà}}, tự là Nguyên-hóa; thực là {{wikt|thần y}} bây giờ, tôi xin đưa đến để yết kiến.
[[Tập tin:汉名医华佗.jpg|phải|nhỏ|Hoa Đà. Tranh vẽ thời nhà Thanh.]]
Được mấy bữa Phiên đem Hoa đà đến.
Sách thấy người mặt còn trẻ, mà tóc bạc phơ phơ, tựa như một ông tiên, tiếp đãi làm một {{wikt|thượng khách}}, rồi mời xem bệnh cho Chu Thái. Hoa Đà xem rồi nói: “Bệnh này chữa thực dễ”. Cho thuốc rịt một tháng Chu Thái khỏi hẳn.
Sách mừng lắm, hậu tạ Hoa Đà rồi tiến binh tiễu trừ giặc núi. Giang-nam bình định cả. Sách chia cho các tướng giữ các cửa ải, một mặt tả biểu tâu về triều đình, một mặt kết giao với {{w|Tào Tháo}}, một mặt đưa thư cho Viên Thuật để đòi lại ngọc-tỉ.
Viên Thuật từ khi nắm được tỷ-phù, có ý muốn giữ lấy để xưng hoàng đế, khi tiếp được thư Tôn Sách, liền đưa thư đáp lại tìm cớ thoái thác không trả, rồi kíp hội [[wikt:trưởng sử|trưởng-sử]] là Dương Đại-tướng; [[wikt:đô đốc|đô-đốc]] là Trương Huân, Kỷ Linh, Kiều Di; [[wikt:thượng tướng|thượng-tướng]] là Lôi Bạc, Trần Lan, cả thảy hơn ba mươi người, bàn với nhau rằng:
- Tôn Sách mượn quân mã của ta để khởi sự, nay đã lấy hết được đất Giang-đông, đã quên ơn ta, lại dám đòi lại ngọc-tỉ, thực là xấc láo, có phương kế gì trị nó đi chăng?
Dương Đại-tướng nói:
- Tôn Sách giữ hiểm sông Tràng-giang, binh giỏi, lương nhiều, cũng chưa dễ trị được. Nay ta nên hãy đánh {{w|Lưu Bị}} trước để báo thù xưa không dưng sang đánh ta đã. Rồi sau ta hãy sửa Tôn Sách, cũng không muộn. Nay tôi xin dâng một kế làm cho Lưu Bị phải bị bắt ngay bây giờ.
Thế là:
''<poem>
Chẳng tới Giang-đông tìm hổ báo;
Lại sang Từ-quận bắt giao long!
</poem>''
Chưa biết kế của Dương Đại-tướng hiến ra làm sao, xem tới [[../Hồi 16|hồi sau]] sẽ hiểu.
{{chú thích cuối trang}}
51dqy7gm7izcdy5sx8sapsgpp2y246e
Kinh Cám Ơn
0
7497
205209
183748
2026-05-09T08:27:19Z
~2026-28121-81
20161
205209
wikitext
text/x-wiki
{{Chất lượng vk|50%}}{{đầu đề
| tựa đề = Kinh Cám Ơn
| tác giả = không rõ
| dịch giả =
| năm =
| phần =
| trước = [[Chủ đề:Tôn giáo]]
| sau =
| ghi chú =
}}
{{văn|
Con cám ơn Đức Chúa Trời là Chúa lòng lành vô cùng chẳng bỏ con, chẳng để con không đời đời, mà lại sinh ra con, cho con được làm người, cùng hằng gìn giữ con, hằng che chở con, lại cho Ngôi Hai xuống thế làm người, chuộc tội chịu chết trên cây Thánh Giá vì con, lại cho con được đạo thánh Đức Chúa Trời, cùng chịu nhiều ơn nhiều phép Hội Thánh nữa, và đã cho phần xác con đêm nay (''sáng thì đọc:'' ngày hôm nay) được mọi sự lành; lại cứu lấy con kẻo phải chết tươi ăn năn tội chẳng kịp. Vậy các Thánh ở trên nước thiên đàng cám ơn Đức Chúa Trời thế nào, thì con cũng hợp cùng các Thánh mà dâng cho Chúa con cùng cám ơn như vậy. Amen.
}}
[[Thể loại:Kinh Kitô giáo]]
4rfcjmtx6qzzfdzpou67im8z0gnocbh
Wikisource:GUS2Wiki
4
46964
205207
205113
2026-05-08T22:07:28Z
Alexis Jazz
15437
Updating gadget usage statistics from [[Special:GadgetUsage]] ([[phab:T121049]])
205207
wikitext
text/x-wiki
{{#ifexist:Project:GUS2Wiki/top|{{/top}}|This page provides a historical record of [[Special:GadgetUsage]] through its page history. To get the data in CSV format, see wikitext. To customize this message or add categories, create [[/top]].}}
Dữ liệu dưới đây được đưa vào vùng nhớ đệm và được cập nhật lần cuối lúc 2026-05-07T11:08:33Z. Tối đa có sẵn {{PLURAL:5000|một kết quả|5000 kết quả}} trong vùng nhớ đệm.
{| class="sortable wikitable"
! Tiện ích !! data-sort-type="number" | Số người dùng !! data-sort-type="number" | Số thành viên tích cực
|-
|AutoOldStyleVi || 7 || 0
|-
|HotCat || 44 || 1
|-
|NopInserter || 9 || 0
|-
|Preload Page Images || 5 || 0
|-
|QualityButton || 12 || 0
|-
|Subpages || 7 || 0
|-
|TemplatePreloader || 37 || 1
|-
|UTCLiveClock || 21 || 0
|-
|addsection-plus || 20 || 0
|-
|edittop || 22 || 1
|-
|mark-proofread || 11 || 0
|-
|navpop || 35 || 0
|-
|purgetab || 26 || 0
|-
|removeAccessKeys || 4 || 0
|-
|wiked || 11 || 0
|}
* [[Đặc biệt:GadgetUsage]]
* [[m:Meta:GUS2Wiki/Script|GUS2Wiki]]
<!-- data in CSV format:
AutoOldStyleVi,7,0
HotCat,44,1
NopInserter,9,0
Preload Page Images,5,0
QualityButton,12,0
Subpages,7,0
TemplatePreloader,37,1
UTCLiveClock,21,0
addsection-plus,20,0
edittop,22,1
mark-proofread,11,0
navpop,35,0
purgetab,26,0
removeAccessKeys,4,0
wiked,11,0
-->
sj7bg8n8zzqeh5hjl5801mpl2rz3hu6
Bản mẫu:Blocked text
10
70169
205210
205107
2026-05-09T08:36:55Z
Hà Nội Bot
20162
thêm người dùng hoặc địa chỉ IP
205210
wikitext
text/x-wiki
<includeonly>__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{replace|{{{blockheader|(userorip) này đã bị [[Wikipedia:Quy định cấm thành viên|cấm]] ''sửa đổi'' tại Wikipedia.}}}|(userorip)|{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP|Tài khoản}}}}'''</span><br/><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng {{{notblocked|''đọc'' các trang Wikipedia}}} của bạn.</span></div>{{#if:{{{noipmessage|}}}||
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số loại cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những người dùng khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:{{{opener|}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>
{{{opener|}}}
}}
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP hoặc dải IP|Tài khoản}} {{{7|}}} đã bị [[Wikisource:Quy định cấm|cấm]] {{{descriptor|}}} bởi {{{1|}}} vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
{{{2|}}}
</div>
Lệnh cấm này {{#if:{{{8|}}}|có hiệu lực là {{{8|}}}}} {{#ifeq:{{{6|}}}|{{int:infiniteblock}}|áp dụng hiệu lực là vô hạn, không có ngày hết hạn.|sẽ hết hạn vào {{{6|}}}.}} ID cấm là {{{5|}}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{closer|Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/{{{4|}}}|gửi thư]] cho bảo quản viên và các thành viên khác.}}}
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{appealinfo|Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[MediaWiki:Blockedtext|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.}}}
</div>
{{#if:{{{usefullink1|}}}|Các liên kết hữu ích khác: [[{{{usefullink1|}}}]] {{#if:{{{usefullink2|}}}|· [[{{{usefullink2}}}]]}} {{#if:{{{usefullink3|}}}|· [[{{{usefullink3}}}]]}} {{#if:{{{usefullink4|}}}|· [[{{{usefullink4}}}]]}} {{#if:{{{usefullink5|}}}|· [[{{{usefullink5}}}]]}} {{#if:{{{usefullink6|}}}|· [[{{{usefullink6}}}]]}} {{#if:{{{usefullink7|}}}|· [[{{{usefullink7}}}]]}} {{#if:{{{usefullink8|}}}|· [[{{{usefullink8}}}]]}} {{#if:{{{usefullink9|}}}|· [[{{{usefullink9}}}]]}}}}
</div></includeonly>
<noinclude>{{Tài liệu}}</noinclude>
63n0dc4x4zb5whg0nln7u1fernrayak
205211
205210
2026-05-09T08:38:04Z
Hà Nội Bot
20162
đổi thành thay thế
205211
wikitext
text/x-wiki
<includeonly>__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{thay thế|{{{blockheader|(userorip) này đã bị [[Wikipedia:Quy định cấm thành viên|cấm]] ''sửa đổi'' tại Wikipedia.}}}|(userorip)|{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP|Tài khoản}}}}'''</span><br/><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng {{{notblocked|''đọc'' các trang Wikipedia}}} của bạn.</span></div>{{#if:{{{noipmessage|}}}||
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số loại cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những người dùng khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:{{{opener|}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>
{{{opener|}}}
}}
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP hoặc dải IP|Tài khoản}} {{{7|}}} đã bị [[Wikisource:Quy định cấm|cấm]] {{{descriptor|}}} bởi {{{1|}}} vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
{{{2|}}}
</div>
Lệnh cấm này {{#if:{{{8|}}}|có hiệu lực là {{{8|}}}}} {{#ifeq:{{{6|}}}|{{int:infiniteblock}}|áp dụng hiệu lực là vô hạn, không có ngày hết hạn.|sẽ hết hạn vào {{{6|}}}.}} ID cấm là {{{5|}}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{closer|Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/{{{4|}}}|gửi thư]] cho bảo quản viên và các thành viên khác.}}}
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{appealinfo|Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[MediaWiki:Blockedtext|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.}}}
</div>
{{#if:{{{usefullink1|}}}|Các liên kết hữu ích khác: [[{{{usefullink1|}}}]] {{#if:{{{usefullink2|}}}|· [[{{{usefullink2}}}]]}} {{#if:{{{usefullink3|}}}|· [[{{{usefullink3}}}]]}} {{#if:{{{usefullink4|}}}|· [[{{{usefullink4}}}]]}} {{#if:{{{usefullink5|}}}|· [[{{{usefullink5}}}]]}} {{#if:{{{usefullink6|}}}|· [[{{{usefullink6}}}]]}} {{#if:{{{usefullink7|}}}|· [[{{{usefullink7}}}]]}} {{#if:{{{usefullink8|}}}|· [[{{{usefullink8}}}]]}} {{#if:{{{usefullink9|}}}|· [[{{{usefullink9}}}]]}}}}
</div></includeonly>
<noinclude>{{Tài liệu}}</noinclude>
4ayrx8sfphble4ep48vbwwymd07pun1
205213
205211
2026-05-09T08:52:00Z
Hà Nội Bot
20162
Đã lùi lại sửa đổi của [[Special:Contributions/Hà Nội Bot|Hà Nội Bot]] ([[User talk:Hà Nội Bot|thảo luận]]) quay về phiên bản cuối của [[User:A09|A09]]
205213
wikitext
text/x-wiki
<includeonly>__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{replace|{{{blockheader|(userorip) này đã bị [[Wikipedia:Quy định cấm thành viên|cấm]] ''sửa đổi'' tại Wikipedia.}}}|(userorip)|{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP|Tài khoản}}}}'''</span><br/><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng {{{notblocked|''đọc'' các trang Wikipedia}}} của bạn.</span></div>{{#if:{{{noipmessage|}}}||
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số loại cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những người dùng khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:{{{opener|}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>
{{{opener|}}}
}}
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP hoặc dải IP|Tài khoản}} {{{7|}}} đã bị [[Wikisource:Quy định cấm|cấm]] {{{descriptor|}}} bởi {{{1|}}} vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
{{{2|}}}
</div>
Lệnh cấm này {{#if:{{{8|}}}|có hiệu lực là {{{8|}}}}} {{#ifeq:{{{6|}}}|{{int:infiniteblock}}|áp dụng hiệu lực là vô hạn, không có ngày hết hạn.|sẽ hết hạn vào {{{6|}}}.}} ID cấm là {{{5|}}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{closer|Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/{{{4|}}}|gửi thư]] cho bảo quản viên và các thành viên khác.}}}
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{appealinfo|Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[MediaWiki:Blockedtext|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.}}}
</div>
{{#if:{{{usefullink1|}}}|Các liên kết hữu ích khác: [[{{{usefullink1|}}}]] {{#if:{{{usefullink2|}}}|· [[{{{usefullink2}}}]]}} {{#if:{{{usefullink3|}}}|· [[{{{usefullink3}}}]]}} {{#if:{{{usefullink4|}}}|· [[{{{usefullink4}}}]]}} {{#if:{{{usefullink5|}}}|· [[{{{usefullink5}}}]]}} {{#if:{{{usefullink6|}}}|· [[{{{usefullink6}}}]]}} {{#if:{{{usefullink7|}}}|· [[{{{usefullink7}}}]]}} {{#if:{{{usefullink8|}}}|· [[{{{usefullink8}}}]]}} {{#if:{{{usefullink9|}}}|· [[{{{usefullink9}}}]]}}}}
</div></includeonly>
<noinclude>{{Tài liệu}}</noinclude>
63n0dc4x4zb5whg0nln7u1fernrayak
205214
205213
2026-05-09T08:55:29Z
Hà Nội Bot
20162
205214
wikitext
text/x-wiki
<includeonly>__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{{blockheader|Bạn đã bị [[Wikisource:Quy định cấm|cấm]] sửa đổi tại Wikisource.}}}<br/>{{#if:{{#invoke:IPAddress|IsIpOrRange|{{{7|}}}|Địa chỉ IP|Tài khoản}}}}'''</span><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng {{{notblocked|''đọc'' các trang Wikisource}}} của bạn.</span></div>{{#if:{{{noipmessage|}}}||
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số loại cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông hay tài khoản cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những người dùng khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:{{{opener|}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>
{{{opener|}}}
}}
Người dùng {{{7|}}} đã bị [[Wikisource:Quy định cấm|cấm]] {{{descriptor|}}} bởi {{{1|}}} vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
{{{2|}}}
</div>
Lệnh cấm này {{#if:{{{8|}}}|có hiệu lực là {{{8|}}}và}} {{#ifeq:{{{6|}}}|{{int:infiniteblock}}|áp dụng hiệu lực là vô hạn, không có ngày hết hạn.|sẽ hết hạn vào {{{6|}}}.}} ID cấm là {{{5|}}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{closer|Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/{{{4|}}}|gửi thư]] cho bảo quản viên và các thành viên khác.}}}
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{appealinfo|Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[MediaWiki:Blockedtext|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.}}}
</div>
{{#if:{{{usefullink1|}}}|Các liên kết hữu ích khác: [[{{{usefullink1|}}}]] {{#if:{{{usefullink2|}}}|· [[{{{usefullink2}}}]]}} {{#if:{{{usefullink3|}}}|· [[{{{usefullink3}}}]]}} {{#if:{{{usefullink4|}}}|· [[{{{usefullink4}}}]]}} {{#if:{{{usefullink5|}}}|· [[{{{usefullink5}}}]]}} {{#if:{{{usefullink6|}}}|· [[{{{usefullink6}}}]]}} {{#if:{{{usefullink7|}}}|· [[{{{usefullink7}}}]]}} {{#if:{{{usefullink8|}}}|· [[{{{usefullink8}}}]]}} {{#if:{{{usefullink9|}}}|· [[{{{usefullink9}}}]]}}}}
</div></includeonly>
<noinclude>{{Tài liệu}}</noinclude>
gqc480rkrog0iewco9iuk2tfrnzc734
205218
205214
2026-05-09T09:10:03Z
Hà Nội Bot
20162
205218
wikitext
text/x-wiki
<includeonly>__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{thay thế|{{{blockheader|(userorip) này đã bị [[Wikipedia:Quy định cấm thành viên|cấm]] ''sửa đổi'' tại Wikisource.}}}|(userorip)|{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP|Tài khoản}}}}'''</span><br/><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng {{{notblocked|''đọc'' các trang Wikisource}}} của bạn.</span></div>{{#if:{{{noipmessage|}}}||
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số tác vụ cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những thành viên khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:{{{opener|}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>
{{{opener|}}}
}}
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP hoặc dải IP|Tài khoản}} {{{7|}}} đã bị [[Wikisource:Quy định cấm|cấm]] {{{descriptor|}}} bởi {{{1|}}} vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
{{{2|}}}
</div>
Lệnh cấm này {{#if:{{{8|}}}|có hiệu lực là {{{8|}}}và}} {{#ifeq:{{{6|}}}|{{int:infiniteblock}}|áp dụng hiệu lực là vô hạn, không có ngày hết hạn.|sẽ hết hạn vào {{{6|}}}.}} ID cấm là #{{{5|}}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{closer|Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/{{{4|}}}|gửi thư]] cho bảo quản viên và các thành viên khác.}}}
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{appealinfo|Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[MediaWiki:Blockedtext|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.}}}
</div>
{{#if:{{{usefullink1|}}}|Các liên kết hữu ích khác: [[{{{usefullink1|}}}]] {{#if:{{{usefullink2|}}}|· [[{{{usefullink2}}}]]}} {{#if:{{{usefullink3|}}}|· [[{{{usefullink3}}}]]}} {{#if:{{{usefullink4|}}}|· [[{{{usefullink4}}}]]}} {{#if:{{{usefullink5|}}}|· [[{{{usefullink5}}}]]}} {{#if:{{{usefullink6|}}}|· [[{{{usefullink6}}}]]}} {{#if:{{{usefullink7|}}}|· [[{{{usefullink7}}}]]}} {{#if:{{{usefullink8|}}}|· [[{{{usefullink8}}}]]}} {{#if:{{{usefullink9|}}}|· [[{{{usefullink9}}}]]}}}}
</div></includeonly>
<noinclude>{{Tài liệu}}</noinclude>
92jnwlugow70q0x4k0bo57yq88t7xnt
205220
205218
2026-05-09T09:11:55Z
Hà Nội Bot
20162
Sửa chính tả
205220
wikitext
text/x-wiki
<includeonly>__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{thay thế|{{{blockheader|(userorip) này đã bị [[Wikipedia:Quy định cấm thành viên|cấm]] ''sửa đổi'' tại Wikisource.}}}|(userorip)|{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP|Tài khoản}}}}'''</span><br/><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng {{{notblocked|''đọc'' các trang Wikisource}}} của bạn.</span></div>{{#if:{{{noipmessage|}}}||
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số tác vụ cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những thành viên khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:{{{opener|}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>
{{{opener|}}}
}}
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP hoặc dải IP|Tài khoản}} {{{7|}}} đã bị [[Wikisource:Quy định cấm|cấm]] {{{descriptor|}}} bởi {{{1|}}} vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
{{{2|}}}
</div>
Lệnh cấm này {{#if:{{{8|}}}|có hiệu lực là {{{8|}}}và}} {{#ifeq:{{{6|}}}|{{int:infiniteblock}}|áp dụng hiệu lực là vô hạn, không có ngày hết hạn.|sẽ hết hạn vào {{{6|}}}.}} ID cấm là #{{{5|}}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{closer|Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/{{{4|}}}|gửi thư]] cho bảo quản viên và các thành viên khác.}}}
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{appealinfo|Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[Wikisource:Quy định cấm|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.}}}
</div>
{{#if:{{{usefullink1|}}}|Các liên kết hữu ích khác: [[{{{usefullink1|}}}]] {{#if:{{{usefullink2|}}}|· [[{{{usefullink2}}}]]}} {{#if:{{{usefullink3|}}}|· [[{{{usefullink3}}}]]}} {{#if:{{{usefullink4|}}}|· [[{{{usefullink4}}}]]}} {{#if:{{{usefullink5|}}}|· [[{{{usefullink5}}}]]}} {{#if:{{{usefullink6|}}}|· [[{{{usefullink6}}}]]}} {{#if:{{{usefullink7|}}}|· [[{{{usefullink7}}}]]}} {{#if:{{{usefullink8|}}}|· [[{{{usefullink8}}}]]}} {{#if:{{{usefullink9|}}}|· [[{{{usefullink9}}}]]}}}}
</div></includeonly>
<noinclude>{{Tài liệu}}</noinclude>
gcmecrtswh0vq0csn0wr09bfkr7sy76
205221
205220
2026-05-09T09:21:26Z
Hà Nội Bot
20162
205221
wikitext
text/x-wiki
<includeonly>__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{thay thế|{{{blockheader|(userorip) này đã bị [[Wikipedia:Quy định cấm thành viên|cấm]] ''sửa đổi'' tại Wikisource.}}}|(userorip)|{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP|Tài khoản}}}}'''</span><br/><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng {{{notblocked|''đọc'' các trang Wikisource}}} của bạn.</span></div>{{#if:{{{noipmessage|}}}||
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số tác vụ cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những thành viên khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:{{{opener|}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>
{{{opener|}}}
}}
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP hoặc dải IP|Tài khoản}} {{{7|}}} đã bị [[Wikisource:Quy định cấm|cấm]] {{{descriptor|}}} bởi {{{1|}}} vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
{{{2|}}}
</div>
Lệnh cấm này {{#if:{{{8|}}}|có hiệu lực là {{{8|}}}và}} {{#ifeq:{{{6|}}}|{{int:infiniteblock}}|không hết hạn.|sẽ hết hạn vào {{{6|}}}.}} ID cấm là #{{{5|}}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{closer|Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/{{{4|}}}|gửi thư]] cho bảo quản viên và các thành viên khác.}}}
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{appealinfo|Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[Wikisource:Quy định cấm|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.}}}
</div>
{{#if:{{{usefullink1|}}}|Các liên kết hữu ích khác: [[{{{usefullink1|}}}]] {{#if:{{{usefullink2|}}}|· [[{{{usefullink2}}}]]}} {{#if:{{{usefullink3|}}}|· [[{{{usefullink3}}}]]}} {{#if:{{{usefullink4|}}}|· [[{{{usefullink4}}}]]}} {{#if:{{{usefullink5|}}}|· [[{{{usefullink5}}}]]}} {{#if:{{{usefullink6|}}}|· [[{{{usefullink6}}}]]}} {{#if:{{{usefullink7|}}}|· [[{{{usefullink7}}}]]}} {{#if:{{{usefullink8|}}}|· [[{{{usefullink8}}}]]}} {{#if:{{{usefullink9|}}}|· [[{{{usefullink9}}}]]}}}}
</div></includeonly>
<noinclude>{{Tài liệu}}</noinclude>
o9xfnqcsdv5079uazyvdpfpqfsyeie6
205222
205221
2026-05-09T09:21:51Z
Hà Nội Bot
20162
cho từ di chuyển
205222
wikitext
text/x-wiki
<includeonly>__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{thay thế|{{{blockheader|(userorip) này đã bị [[Wikipedia:Quy định cấm thành viên|cấm]] ''sửa đổi'' tại Wikisource.}}}|(userorip)|{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP|Tài khoản}}}}'''</span><br/><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng {{{notblocked|''đọc'' các trang Wikisource}}} của bạn.</span></div>{{#if:{{{noipmessage|}}}||
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số tác vụ cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những thành viên khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:{{{opener|}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>
{{{opener|}}}
}}
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP hoặc dải IP|Tài khoản}} {{{7|}}} đã bị [[Wikisource:Quy định cấm|cấm]] {{{descriptor|}}} bởi {{{1|}}} vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
{{{2|}}}
</div>
Lệnh cấm này {{#if:{{{8|}}}|có hiệu lực là {{{8|}}}và}} sẽ {{#ifeq:{{{6|}}}|{{int:infiniteblock}}|không hết hạn.|hết hạn vào {{{6|}}}.}} ID cấm là #{{{5|}}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{closer|Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/{{{4|}}}|gửi thư]] cho bảo quản viên và các thành viên khác.}}}
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{appealinfo|Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[Wikisource:Quy định cấm|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.}}}
</div>
{{#if:{{{usefullink1|}}}|Các liên kết hữu ích khác: [[{{{usefullink1|}}}]] {{#if:{{{usefullink2|}}}|· [[{{{usefullink2}}}]]}} {{#if:{{{usefullink3|}}}|· [[{{{usefullink3}}}]]}} {{#if:{{{usefullink4|}}}|· [[{{{usefullink4}}}]]}} {{#if:{{{usefullink5|}}}|· [[{{{usefullink5}}}]]}} {{#if:{{{usefullink6|}}}|· [[{{{usefullink6}}}]]}} {{#if:{{{usefullink7|}}}|· [[{{{usefullink7}}}]]}} {{#if:{{{usefullink8|}}}|· [[{{{usefullink8}}}]]}} {{#if:{{{usefullink9|}}}|· [[{{{usefullink9}}}]]}}}}
</div></includeonly>
<noinclude>{{Tài liệu}}</noinclude>
otbfngf9u9um8m1exp9wp9648xn5l7l
205223
205222
2026-05-09T10:42:26Z
Hà Nội Bot
20162
Thêm để hiểu biết hơn
205223
wikitext
text/x-wiki
<includeonly>__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{thay thế|{{{blockheader|(userorip) này đã bị [[Wikipedia:Quy định cấm thành viên|cấm]] ''sửa đổi'' tại Wikisource.}}}|(userorip)|{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP|Tài khoản}}}}'''</span><br/><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng {{{notblocked|''đọc'' các trang Wikisource}}} của bạn.</span></div>{{#if:{{{noipmessage|}}}||
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số tác vụ cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những thành viên khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:{{{opener|}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>
{{{opener|}}}
}}
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP hoặc dải IP|Tài khoản}} {{{7|}}} đã bị [[Wikisource:Quy định cấm|cấm]] {{{descriptor|}}} bởi {{{1|}}} vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
{{{2|}}}
</div>
{{#if:{{{6|}}}|Lệnh cấm này {{#if:{{{8|}}}|có hiệu lực là {{{8|}}}và}} sẽ {{#ifeq:{{{6|}}}|{{int:infiniteblock}}|không hết hạn|hết hạn vào {{{6|}}}}}{{#if:{{{blockid|}}}|, ID cấm là #{{{5|}}}}}.}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{closer|Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/{{{4|}}}|gửi thư]] cho bảo quản viên và các thành viên khác.}}}
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{appealinfo|Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[Wikisource:Quy định cấm|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.}}}
</div>
{{#if:{{{usefullink1|}}}|Các liên kết hữu ích khác: [[{{{usefullink1|}}}]] {{#if:{{{usefullink2|}}}|· [[{{{usefullink2}}}]]}} {{#if:{{{usefullink3|}}}|· [[{{{usefullink3}}}]]}} {{#if:{{{usefullink4|}}}|· [[{{{usefullink4}}}]]}} {{#if:{{{usefullink5|}}}|· [[{{{usefullink5}}}]]}} {{#if:{{{usefullink6|}}}|· [[{{{usefullink6}}}]]}} {{#if:{{{usefullink7|}}}|· [[{{{usefullink7}}}]]}} {{#if:{{{usefullink8|}}}|· [[{{{usefullink8}}}]]}} {{#if:{{{usefullink9|}}}|· [[{{{usefullink9}}}]]}}}}
</div></includeonly>
<noinclude>{{Tài liệu}}</noinclude>
bt0jb6jsvv2sjf8sk0c73n6g4h5w3uf
Bản mẫu:Blocked text/tài liệu
10
70170
205216
199741
2026-05-09T09:06:51Z
Hà Nội Bot
20162
Thêm tham số bản mẫu
205216
wikitext
text/x-wiki
{{Trang con tài liệu}}
<!-- VUI LÒNG GHI THỂ LOẠI VÀO CUỐI TRANG, VÀ ĐẶT LIÊN KẾT LIÊN WIKI TẠI WIKIDATA -->
==Cách sử dụng==
Bản mẫu này được sử dụng trong thông báo hệ thống để thông báo cho thành viên đang cố gắng sửa đổi rằng họ đã bị cấm.
==Ví dụ==
===Cấm IP tạm thời===
{{Blocked text|[[Wikisource:Bảo quản viên|Bảo quản viên]]|Lý do nào đó|192.0.0.1|Bảo quản viên|12345|31 tháng 12 năm 2099, 11:03|192.0.0.1|1 tháng 1 năm 1970, 00:00
|usefullink1 = Wikisource:Quy định cấm{{!}}Quy định cấm
|usefullink2 = Trợ giúp:Tôi đã bị cấm
}}
===Cấm tài khoản vô hạn===
{{Blocked text|[[Wikisource:Bảo quản viên|Bảo quản viên]]|Lý do nào đó|192.0.0.1|Bảo quản viên|12345|{{int:infiniteblock}}|Thành viên bị cấm|1 tháng 1 năm 1970, 00:00
|usefullink1 = Wikisource:Quy định cấm{{!}}Quy định cấm
|usefullink2 = Trợ giúp:Tôi đã bị cấm
}}
== Template data ==
<templatedata>
{
"params": {
"1": {
"suggestedvalues": [
"$1"
],
"label": "Link to blocking admin's userpage"
},
"2": {
"suggestedvalues": [
"$2"
],
"label": "Block reason"
},
"3": {
"suggestedvalues": [
"$3"
],
"label": "IP address of blocked user"
},
"4": {
"suggestedvalues": [
"$4"
],
"label": "Blocking admin's name"
},
"5": {
"suggestedvalues": [
"$5"
],
"label": "Block ID"
},
"6": {
"suggestedvalues": [
"$6"
],
"label": "Timestamp of block expiration time"
},
"7": {
"suggestedvalues": [
"$7"
],
"label": "Blocked user"
},
"8": {
"suggestedvalues": [
"$8"
],
"label": "Timestamp of block start time"
},
"blockheader": {
"label": "Block header",
"description": "The header of the block message. The string \"(userorip)\" will be replaced with \"account\" or \"IP address\" depending on whether the blocked target is an account or an IP."
},
"notblocked": {
"label": "Not blocked",
"description": "The actions that are not blocked."
},
"noipmessage": {
"label": "No IP message",
"description": "Whether the message shown to IPs should be hidden"
},
"opener": {
"label": "Opener",
"description": "The text to open the block notice (after the IP message but before the block details)"
},
"descriptor": {
"label": "Descriptor",
"description": "An adverb descriptor for the \"blocked\" verb (like \"partially\" or \"globally\")"
},
"closer": {
"label": "Closer",
"description": "The text to close the block notice (before details about appeals)"
},
"appealinfo": {
"label": "Appeal Info",
"description": "Information about appealing the block"
},
"usefullink1": {},
"usefullink2": {},
"usefullink3": {},
"usefullink4": {},
"usefullink5": {},
"usefullink6": {},
"usefullink7": {},
"usefullink8": {},
"usefullink9": {},
"blockid": {
"label": "Show Block ID",
"description": "Whether the block ID should be visible on the block message"
}
},
"paramOrder": [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"blockheader",
"notblocked",
"noipmessage",
"opener",
"blockid",
"descriptor",
"closer",
"appealinfo",
"usefullink1",
"usefullink2",
"usefullink3",
"usefullink4",
"usefullink5",
"usefullink6",
"usefullink7",
"usefullink8",
"usefullink9"
]
}
</templatedata>
<includeonly>{{sandbox other||
<!-- Xin hãy thêm thể loại vào phía dưới dòng này, để bổ sung liên kết liên wiki vào Wikidata -->
}}</includeonly>
d0f33t2yv9xgu2tz3blj4de4nj2ixax
Bản mẫu:Thay thế
10
72200
205212
2026-05-09T08:38:30Z
Hà Nội Bot
20162
[[w:WP:TTL|←]]Trang mới: “{{#gọi:String|replace|source={{{1}}}|{{{2}}}|{{{3}}}|count={{{số lần|{{{count|}}}}}}}}<noinclude> {{Tài liệu}} </noinclude>”
205212
wikitext
text/x-wiki
{{#gọi:String|replace|source={{{1}}}|{{{2}}}|{{{3}}}|count={{{số lần|{{{count|}}}}}}}}<noinclude>
{{Tài liệu}}
</noinclude>
4j7e0rysgdhums6xyxngm1we9c56ang
Trợ giúp:Tôi đã bị cấm
12
72201
205215
2026-05-09T09:04:17Z
Hà Nội Bot
20162
[[w:WP:TTL|←]]Trang mới: “{| | width="49%" valign="top" | ==Nhưng tôi vô tội!== Đôi khi những dải IP hoặc proxy dùng chung bị cấm không được sửa đổi trang ở Wikisource, vì thế bạn có thể bị cấm tuy bạn không làm gì sai trái. Nếu bạn gặp trường hợp này thì xin đọc lý do trên. Ngoài ra, một số địa chỉ IP riêng có thể bị cấm, thường hết hạn trong vòng 24 giờ. Đôi khi có người dùng I…”
205215
wikitext
text/x-wiki
{|
| width="49%" valign="top" |
==Nhưng tôi vô tội!==
Đôi khi những dải IP hoặc proxy dùng chung bị cấm không được sửa đổi trang ở Wikisource, vì thế bạn có thể bị cấm tuy bạn không làm gì sai trái. Nếu bạn gặp trường hợp này thì xin đọc lý do trên.
Ngoài ra, một số địa chỉ IP riêng có thể bị cấm, thường hết hạn trong vòng 24 giờ. Đôi khi có người dùng IP động bị [[w:Wikipedia:Khóa tự động|cấm bất ngờ]], do địa chỉ IP họ đang sử dụng được một tài khoản bị cấm khác sử dụng.
Chúng tôi xin lỗi vì việc cấm có thể gây bất tiện đối với bạn. Nếu vấn đề này xảy ra nhiều lần, chúng tôi khuyên bạn nên liên lạc với [[w:ISP|nhà cung cấp dịch vụ Internet]] hoặc phòng IT và yêu cầu họ liên hệ với [[m:XFF project|dự án XFF]] của [[w:Wikimedia Foundation|Wikimedia]] để kích hoạt tiêu đề HTTP [[w:en:X-Forwarded-For|X-Forwarded-For]] trên [[w:máy chủ proxy|máy chủ proxy]] của họ. Điều này sẽ giúp bạn giảm nguy cơ bị ảnh hưởng bởi các lần cấm tự động về sau.
| width="2%" |
| class="plainlinks" width="49%" valign="top" |
==Bây giờ tôi cần làm gì?==
'''Địa chỉ IP của bạn là <code>$3</code>. Xin hãy đưa địa chỉ này, cùng với tên đăng nhập (nếu bạn đã mở tài khoản), khi thảo luận về việc cấm này.'''<br /><br />
Bạn có thể [[{{ns:Special}}:Emailuser/$4|gửi thư điện tử đến $4]] hay một trong số các [[{{ns:Project}}:Bảo quản viên|bảo quản viên]] khác để thảo luận về việc cấm này. Bạn cũng được sửa đổi [[{{ns:Special}}:Mytalk|trang thảo luận của mình]]. Nếu bạn cảm thấy rằng [[{{ns:Project}}:Quy định cấm|quy định cấm]] đã bị vi phạm, bạn có thể thảo luận công khai trên [[mail:wikivi-l|danh sách gửi thư WikiVI-l]].
Xin lưu ý, trước khi bạn có thể sử dụng tính năng “Gửi thư cho người này”, bạn cần phải mở tài khoản ở Wikisource và điền vào địa chỉ thư điện tử hợp lệ trong [[{{ns:Special}}:Preferences|tùy chọn cá nhân]], đồng thời bạn không bị cấm dùng tính năng này.
Bạn vẫn có thể tải xuống [{{fullurle:{{FULLPAGENAME}}|action=raw}} mã nguồn] của trang này hay [[{{ns:Special}}:Export|xuất ra trang]].
|}
==Tôi đến từ Trung Quốc==
Xin hãy đọc [[w:Wikipedia:Tor|Wikipedia:Tor]] để biết cách truy cập vào Wikisource không cần phải giấu địa chỉ IP.
9ekciu5csa2lqjo7rqbyatfry90ensz
Mô đun:IPAddress
828
72202
205217
2026-05-09T09:07:25Z
Hà Nội Bot
20162
[[w:WP:TTL|←]]Trang mới: “local p = {} function p._isIpV6(s) local dcolon, groups if type(s) ~= "string" or s:len() == 0 or s:find("[^:%x]") -- only colon and hex digits are legal chars or s:find("^:[^:]") -- can begin or end with :: but not with single : or s:find("[^:]:$") or s:find(":::") then return false end s, dcolon = s:gsub("::", ":") if dcolon > 1 then return false end -- at most one :: s = s:gsub("^:?", ":") -- prepend : if needed, upper s, groups = s…”
205217
Scribunto
text/plain
local p = {}
function p._isIpV6(s)
local dcolon, groups
if type(s) ~= "string"
or s:len() == 0
or s:find("[^:%x]") -- only colon and hex digits are legal chars
or s:find("^:[^:]") -- can begin or end with :: but not with single :
or s:find("[^:]:$")
or s:find(":::")
then
return false
end
s, dcolon = s:gsub("::", ":")
if dcolon > 1 then return false end -- at most one ::
s = s:gsub("^:?", ":") -- prepend : if needed, upper
s, groups = s:gsub(":%x%x?%x?%x?", "") -- remove valid groups, and count them
return ( (dcolon == 1 and groups < 8) or (dcolon == 0 and groups == 8) )
and ( s:len() == 0 or (dcolon == 1 and s == ":") ) -- might be one dangling : if original ended with ::
end
function p._isIpV4(s)
local function legal(n) return (tonumber(n) or 256) < 256 and not n:match("^0%d") end
if type(s) ~= "string" then return false end
local p1, p2, p3, p4 = s:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
return legal(p1) and legal(p2) and legal(p3) and legal(p4)
end
function p._isIp(s)
return p._isIpV4(s) and "4" or p._isIpV6(s) and "6"
end
function p._isIpOrRange(s)
local modip = require('Module:IP')
local success, ip = pcall(modip.IPAddress.new, s)
if success then
return 'ip'
end
success, ip = pcall(modip.Subnet.new, s)
if success then
return 'range'
end
return ''
end
local function input(frame)
-- Return input parameter after replacing any of following directional markers.
-- LRM : LEFT-TO-RIGHT MARK (U+200E) : hex e2 80 8e = 226 128 142
-- LRE : LEFT-TO-RIGHT EMBEDDING (U+202A) : hex e2 80 aa = 226 128 170
-- PDF : POP DIRECTIONAL FORMATTING (U+202C) : hex e2 80 ac = 226 128 172
-- This is required for MediaWiki:Blockedtext message.
return (frame.args[1] or ''):gsub('\226\128[\142\170\172]', ' ') -- replace LRM, LRE, PDF with space delimiter
end
function p.isIpV6(frame) return p._isIpV6(input(frame)) and "1" or "0" end
function p.isIpV4(frame) return p._isIpV4(input(frame)) and "1" or "0" end
function p.isIp(frame) return p._isIp(input(frame)) or "" end
function p.isIpOrRange(frame)
-- {{#invoke:IPAddress|isIpOrRange|x}} → 'ip' (IPv4/IPv6) or 'range' (CIDR IPv4/IPv6) or '' (invalid)
return p._isIpOrRange(input(frame))
end
return p
g17okvs0smqjz1wuwjjald1ec1f8wh2
Mô đun:IP
828
72203
205219
2026-05-09T09:10:37Z
Hà Nội Bot
20162
[[w:WP:TTL|←]]Trang mới: “-- IP library -- This library contains classes for working with IP addresses and IP ranges. -- Load modules require('strict') local bit32 = require('bit32') local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local checkTypeMulti = libraryUtil.checkTypeMulti local makeCheckSelfFunction = libraryUtil.makeCheckSelfFunction -- Constants local V4 = 'IPv4' local V6 = 'IPv6' ------------------------------------------------------…”
205219
Scribunto
text/plain
-- IP library
-- This library contains classes for working with IP addresses and IP ranges.
-- Load modules
require('strict')
local bit32 = require('bit32')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
local makeCheckSelfFunction = libraryUtil.makeCheckSelfFunction
-- Constants
local V4 = 'IPv4'
local V6 = 'IPv6'
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function makeValidationFunction(className, isObjectFunc)
-- Make a function for validating a specific object.
return function (methodName, argIdx, arg)
if not isObjectFunc(arg) then
error(string.format(
"bad argument #%d to '%s' (not a valid %s object)",
argIdx, methodName, className
), 3)
end
end
end
--------------------------------------------------------------------------------
-- Collection class
-- This is a table used to hold items.
--------------------------------------------------------------------------------
local Collection = {}
Collection.__index = Collection
function Collection:add(item)
if item ~= nil then
self.n = self.n + 1
self[self.n] = item
end
end
function Collection:join(sep)
return table.concat(self, sep)
end
function Collection:remove(pos)
if self.n > 0 and (pos == nil or (0 < pos and pos <= self.n)) then
self.n = self.n - 1
return table.remove(self, pos)
end
end
function Collection:sort(comp)
table.sort(self, comp)
end
function Collection:deobjectify()
-- Turns the collection into a plain array without any special properties
-- or methods.
self.n = nil
setmetatable(self, nil)
end
function Collection.new()
return setmetatable({n = 0}, Collection)
end
--------------------------------------------------------------------------------
-- RawIP class
-- Numeric representation of an IPv4 or IPv6 address. Used internally.
-- A RawIP object is constructed by adding data to a Collection object and
-- then giving it a new metatable. This is to avoid the memory overhead of
-- copying the data to a new table.
--------------------------------------------------------------------------------
local RawIP = {}
RawIP.__index = RawIP
-- Constructors
function RawIP.newFromIPv4(ipStr)
-- Return a RawIP object if ipStr is a valid IPv4 string. Otherwise,
-- return nil.
-- This representation is for compatibility with IPv6 addresses.
local octets = Collection.new()
local s = ipStr:match('^%s*(.-)%s*$') .. '.'
for item in s:gmatch('(.-)%.') do
octets:add(item)
end
if octets.n == 4 then
for i, s in ipairs(octets) do
if s:match('^%d+$') then
local num = tonumber(s)
if 0 <= num and num <= 255 then
if num > 0 and s:match('^0') then
-- A redundant leading zero is for an IP in octal.
return nil
end
octets[i] = num
else
return nil
end
else
return nil
end
end
local parts = Collection.new()
for i = 1, 3, 2 do
parts:add(octets[i] * 256 + octets[i+1])
end
return setmetatable(parts, RawIP)
end
return nil
end
function RawIP.newFromIPv6(ipStr)
-- Return a RawIP object if ipStr is a valid IPv6 string. Otherwise,
-- return nil.
ipStr = ipStr:match('^%s*(.-)%s*$')
local _, n = ipStr:gsub(':', ':')
if n < 7 then
ipStr = ipStr:gsub('::', string.rep(':', 9 - n))
end
local parts = Collection.new()
for item in (ipStr .. ':'):gmatch('(.-):') do
parts:add(item)
end
if parts.n == 8 then
for i, s in ipairs(parts) do
if s == '' then
parts[i] = 0
else
if s:match('^%x+$') then
local num = tonumber(s, 16)
if num and 0 <= num and num <= 65535 then
parts[i] = num
else
return nil
end
else
return nil
end
end
end
return setmetatable(parts, RawIP)
end
return nil
end
function RawIP.newFromIP(ipStr)
-- Return a new RawIP object from either an IPv4 string or an IPv6
-- string. If ipStr is not a valid IPv4 or IPv6 string, then return
-- nil.
return RawIP.newFromIPv4(ipStr) or RawIP.newFromIPv6(ipStr)
end
-- Methods
function RawIP:getVersion()
-- Return a string with the version of the IP protocol we are using.
return self.n == 2 and V4 or V6
end
function RawIP:isIPv4()
-- Return true if this is an IPv4 representation, and false otherwise.
return self.n == 2
end
function RawIP:isIPv6()
-- Return true if this is an IPv6 representation, and false otherwise.
return self.n == 8
end
function RawIP:getBitLength()
-- Return the bit length of the IP address.
return self.n * 16
end
function RawIP:getAdjacent(previous)
-- Return a RawIP object for an adjacent IP address. If previous is true
-- then the previous IP is returned; otherwise the next IP is returned.
-- Will wraparound:
-- next 255.255.255.255 → 0.0.0.0
-- ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff → ::
-- previous 0.0.0.0 → 255.255.255.255
-- :: → ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
local result = Collection.new()
result.n = self.n
local carry = previous and 0xffff or 1
for i = self.n, 1, -1 do
local sum = self[i] + carry
if sum >= 0x10000 then
carry = previous and 0x10000 or 1
sum = sum - 0x10000
else
carry = previous and 0xffff or 0
end
result[i] = sum
end
return setmetatable(result, RawIP)
end
function RawIP:getPrefix(bitLength)
-- Return a RawIP object for the prefix of the current IP Address with a
-- bit length of bitLength.
local result = Collection.new()
result.n = self.n
for i = 1, self.n do
if bitLength > 0 then
if bitLength >= 16 then
result[i] = self[i]
bitLength = bitLength - 16
else
result[i] = bit32.replace(self[i], 0, 0, 16 - bitLength)
bitLength = 0
end
else
result[i] = 0
end
end
return setmetatable(result, RawIP)
end
function RawIP:getHighestHost(bitLength)
-- Return a RawIP object for the highest IP with the prefix of length
-- bitLength. In other words, the network (the most-significant bits)
-- is the same as the current IP's, but the host bits (the
-- least-significant bits) are all set to 1.
local bits = self.n * 16
local width
if bitLength <= 0 then
width = bits
elseif bitLength >= bits then
width = 0
else
width = bits - bitLength
end
local result = Collection.new()
result.n = self.n
for i = self.n, 1, -1 do
if width > 0 then
if width >= 16 then
result[i] = 0xffff
width = width - 16
else
result[i] = bit32.replace(self[i], 0xffff, 0, width)
width = 0
end
else
result[i] = self[i]
end
end
return setmetatable(result, RawIP)
end
function RawIP:_makeIPv6String()
-- Return an IPv6 string representation of the object. Behavior is
-- undefined if the current object is IPv4.
local z1, z2 -- indices of run of zeroes to be displayed as "::"
local zstart, zcount
for i = 1, 9 do
-- Find left-most occurrence of longest run of two or more zeroes.
if i < 9 and self[i] == 0 then
if zstart then
zcount = zcount + 1
else
zstart = i
zcount = 1
end
else
if zcount and zcount > 1 then
if not z1 or zcount > z2 - z1 + 1 then
z1 = zstart
z2 = zstart + zcount - 1
end
end
zstart = nil
zcount = nil
end
end
local parts = Collection.new()
for i = 1, 8 do
if z1 and z1 <= i and i <= z2 then
if i == z1 then
if z1 == 1 or z2 == 8 then
if z1 == 1 and z2 == 8 then
return '::'
end
parts:add(':')
else
parts:add('')
end
end
else
parts:add(string.format('%x', self[i]))
end
end
return parts:join(':')
end
function RawIP:_makeIPv4String()
-- Return an IPv4 string representation of the object. Behavior is
-- undefined if the current object is IPv6.
local parts = Collection.new()
for i = 1, 2 do
local w = self[i]
parts:add(math.floor(w / 256))
parts:add(w % 256)
end
return parts:join('.')
end
function RawIP:__tostring()
-- Return a string equivalent to given IP address (IPv4 or IPv6).
if self.n == 2 then
return self:_makeIPv4String()
else
return self:_makeIPv6String()
end
end
function RawIP:__lt(obj)
if self.n == obj.n then
for i = 1, self.n do
if self[i] ~= obj[i] then
return self[i] < obj[i]
end
end
return false
end
return self.n < obj.n
end
function RawIP:__eq(obj)
if self.n == obj.n then
for i = 1, self.n do
if self[i] ~= obj[i] then
return false
end
end
return true
end
return false
end
--------------------------------------------------------------------------------
-- Initialize private methods available to IPAddress and Subnet
--------------------------------------------------------------------------------
-- Both IPAddress and Subnet need access to each others' private constructor
-- functions. IPAddress must be able to make Subnet objects from CIDR strings
-- and from RawIP objects, and Subnet must be able to make IPAddress objects
-- from IP strings and from RawIP objects. These constructors must all be
-- private to ensure correct error levels and to stop other modules from having
-- to worry about RawIP objects. Because they are private, they must be
-- initialized here.
local makeIPAddress, makeIPAddressFromRaw, makeSubnet, makeSubnetFromRaw
-- Objects need to be able to validate other objects that they are passed
-- as input, so initialize those functions here as well.
local validateCollection, validateIPAddress, validateSubnet
--------------------------------------------------------------------------------
-- IPAddress class
-- Represents a single IPv4 or IPv6 address.
--------------------------------------------------------------------------------
local IPAddress = {}
do
-- dataKey is a unique key to access objects' internal data. This is needed
-- to access the RawIP objects contained in other IPAddress objects so that
-- they can be compared with the current object's RawIP object. This data
-- is not available to other classes or other modules.
local dataKey = {}
-- Private static methods
local function isIPAddressObject(val)
return type(val) == 'table' and val[dataKey] ~= nil
end
validateIPAddress = makeValidationFunction('IPAddress', isIPAddressObject)
-- Metamethods that don't need upvalues
local function ipEquals(ip1, ip2)
return ip1[dataKey].rawIP == ip2[dataKey].rawIP
end
local function ipLessThan(ip1, ip2)
return ip1[dataKey].rawIP < ip2[dataKey].rawIP
end
local function concatIP(ip, val)
return tostring(ip) .. tostring(val)
end
local function ipToString(ip)
return ip:getIP()
end
-- Constructors
makeIPAddressFromRaw = function (rawIP)
-- Constructs a new IPAddress object from a rawIP object. This function
-- is for internal use; it is called by IPAddress.new and from other
-- IPAddress methods, and should be available to the Subnet class, but
-- should not be available to other modules.
assert(type(rawIP) == 'table', 'rawIP was type ' .. type(rawIP) .. '; expected type table')
-- Set up structure
local obj = {}
local data = {}
data.rawIP = rawIP
-- A function to check whether methods are called with a valid self
-- parameter.
local checkSelf = makeCheckSelfFunction(
'IP',
'ipAddress',
obj,
'IPAddress object'
)
-- Public methods
function obj:getIP()
checkSelf(self, 'getIP')
return tostring(data.rawIP)
end
function obj:getVersion()
checkSelf(self, 'getVersion')
return data.rawIP:getVersion()
end
function obj:isIPv4()
checkSelf(self, 'isIPv4')
return data.rawIP:isIPv4()
end
function obj:isIPv6()
checkSelf(self, 'isIPv6')
return data.rawIP:isIPv6()
end
function obj:isInCollection(collection)
checkSelf(self, 'isInCollection')
validateCollection('isInCollection', 1, collection)
return collection:containsIP(self)
end
function obj:isInSubnet(subnet)
checkSelf(self, 'isInSubnet')
local tp = type(subnet)
if tp == 'string' then
subnet = makeSubnet(subnet)
elseif tp == 'table' then
validateSubnet('isInSubnet', 1, subnet)
else
checkTypeMulti('isInSubnet', 1, subnet, {'string', 'table'})
end
return subnet:containsIP(self)
end
function obj:getSubnet(bitLength)
checkSelf(self, 'getSubnet')
checkType('getSubnet', 1, bitLength, 'number')
if bitLength < 0
or bitLength > data.rawIP:getBitLength()
or bitLength ~= math.floor(bitLength)
then
error(string.format(
"bad argument #1 to 'getSubnet' (must be an integer between 0 and %d)",
data.rawIP:getBitLength()
), 2)
end
return makeSubnetFromRaw(data.rawIP, bitLength)
end
function obj:getNextIP()
checkSelf(self, 'getNextIP')
return makeIPAddressFromRaw(data.rawIP:getAdjacent())
end
function obj:getPreviousIP()
checkSelf(self, 'getPreviousIP')
return makeIPAddressFromRaw(data.rawIP:getAdjacent(true))
end
-- Metamethods
return setmetatable(obj, {
__eq = ipEquals,
__lt = ipLessThan,
__concat = concatIP,
__tostring = ipToString,
__index = function (self, key)
-- If any code knows the unique data key, allow it to access
-- the data table.
if key == dataKey then
return data
end
end,
__metatable = false, -- don't allow access to the metatable
})
end
makeIPAddress = function (ip)
local rawIP = RawIP.newFromIP(ip)
if not rawIP then
error(string.format("'%s' is an invalid IP address", ip), 3)
end
return makeIPAddressFromRaw(rawIP)
end
function IPAddress.new(ip)
checkType('IPAddress.new', 1, ip, 'string')
return makeIPAddress(ip)
end
end
--------------------------------------------------------------------------------
-- Subnet class
-- Represents a block of IPv4 or IPv6 addresses.
--------------------------------------------------------------------------------
local Subnet = {}
do
-- uniqueKey is a unique, private key used to test whether a given object
-- is a Subnet object.
local uniqueKey = {}
-- Metatable
local mt = {
__index = function (self, key)
if key == uniqueKey then
return true
end
end,
__eq = function (self, obj)
return self:getCIDR() == obj:getCIDR()
end,
__concat = function (self, obj)
return tostring(self) .. tostring(obj)
end,
__tostring = function (self)
return self:getCIDR()
end,
__metatable = false
}
-- Private static methods
local function isSubnetObject(val)
-- Return true if val is a Subnet object, and false otherwise.
return type(val) == 'table' and val[uniqueKey] ~= nil
end
-- Function to validate subnet objects.
-- Params:
-- methodName (string) - the name of the method being validated
-- argIdx (number) - the position of the argument in the argument list
-- arg - the argument to be validated
validateSubnet = makeValidationFunction('Subnet', isSubnetObject)
-- Constructors
makeSubnetFromRaw = function (rawIP, bitLength)
-- Set up structure
local obj = setmetatable({}, mt)
local data = {
rawIP = rawIP,
bitLength = bitLength,
}
-- A function to check whether methods are called with a valid self
-- parameter.
local checkSelf = makeCheckSelfFunction(
'IP',
'subnet',
obj,
'Subnet object'
)
-- Public methods
function obj:getPrefix()
checkSelf(self, 'getPrefix')
if not data.prefix then
data.prefix = makeIPAddressFromRaw(
data.rawIP:getPrefix(data.bitLength)
)
end
return data.prefix
end
function obj:getHighestIP()
checkSelf(self, 'getHighestIP')
if not data.highestIP then
data.highestIP = makeIPAddressFromRaw(
data.rawIP:getHighestHost(data.bitLength)
)
end
return data.highestIP
end
function obj:getBitLength()
checkSelf(self, 'getBitLength')
return data.bitLength
end
function obj:getCIDR()
checkSelf(self, 'getCIDR')
return string.format(
'%s/%d',
tostring(self:getPrefix()), self:getBitLength()
)
end
function obj:getVersion()
checkSelf(self, 'getVersion')
return data.rawIP:getVersion()
end
function obj:isIPv4()
checkSelf(self, 'isIPv4')
return data.rawIP:isIPv4()
end
function obj:isIPv6()
checkSelf(self, 'isIPv6')
return data.rawIP:isIPv6()
end
function obj:containsIP(ip)
checkSelf(self, 'containsIP')
local tp = type(ip)
if tp == 'string' then
ip = makeIPAddress(ip)
elseif tp == 'table' then
validateIPAddress('containsIP', 1, ip)
else
checkTypeMulti('containsIP', 1, ip, {'string', 'table'})
end
if self:getVersion() == ip:getVersion() then
return self:getPrefix() <= ip and ip <= self:getHighestIP()
end
return false
end
function obj:overlapsCollection(collection)
checkSelf(self, 'overlapsCollection')
validateCollection('overlapsCollection', 1, collection)
return collection:overlapsSubnet(self)
end
function obj:overlapsSubnet(subnet)
checkSelf(self, 'overlapsSubnet')
local tp = type(subnet)
if tp == 'string' then
subnet = makeSubnet(subnet)
elseif tp == 'table' then
validateSubnet('overlapsSubnet', 1, subnet)
else
checkTypeMulti('overlapsSubnet', 1, subnet, {'string', 'table'})
end
if self:getVersion() == subnet:getVersion() then
return (
subnet:getHighestIP() >= self:getPrefix() and
subnet:getPrefix() <= self:getHighestIP()
)
end
return false
end
function obj:walk()
checkSelf(self, 'walk')
local started
local current = self:getPrefix()
local highest = self:getHighestIP()
return function ()
if not started then
started = true
return current
end
if current < highest then
current = current:getNextIP()
return current
end
end
end
return obj
end
makeSubnet = function (cidr)
-- Return a Subnet object from a CIDR string. If the CIDR string is
-- invalid, throw an error.
local lhs, rhs = cidr:match('^%s*(.-)/(%d+)%s*$')
if lhs then
local bits = lhs:find(':', 1, true) and 128 or 32
local n = tonumber(rhs)
if n and n <= bits and (n == 0 or not rhs:find('^0')) then
-- The right-hand side is a number between 0 and 32 (for IPv4)
-- or 0 and 128 (for IPv6) and doesn't have any leading zeroes.
local base = RawIP.newFromIP(lhs)
if base then
-- The left-hand side is a valid IP address.
local prefix = base:getPrefix(n)
if base == prefix then
-- The left-hand side is the lowest IP in the subnet.
return makeSubnetFromRaw(prefix, n)
end
end
end
end
error(string.format("'%s' is an invalid CIDR string", cidr), 3)
end
function Subnet.new(cidr)
checkType('Subnet.new', 1, cidr, 'string')
return makeSubnet(cidr)
end
end
--------------------------------------------------------------------------------
-- Ranges class
-- Holds a list of IPAdress pairs representing contiguous IP ranges.
--------------------------------------------------------------------------------
local Ranges = Collection.new()
Ranges.__index = Ranges
function Ranges.new()
return setmetatable({}, Ranges)
end
function Ranges:add(ip1, ip2)
validateIPAddress('add', 1, ip1)
if ip2 ~= nil then
validateIPAddress('add', 2, ip2)
if ip1 > ip2 then
error('The first IP must be less than or equal to the second', 2)
end
end
Collection.add(self, {ip1, ip2 or ip1})
end
function Ranges:merge()
self:sort(
function (lhs, rhs)
-- Sort by second value, then first.
if lhs[2] == rhs[2] then
return lhs[1] < rhs[1]
end
return lhs[2] < rhs[2]
end
)
local pos = self.n
while pos > 1 do
for i = pos - 1, 1, -1 do
local ip1 = self[i][2]
local ip2 = ip1:getNextIP()
if ip2 < ip1 then
ip2 = ip1 -- don't wrap around
end
if self[pos][1] > ip2 then
break
end
ip1 = self[i][1]
ip2 = self[pos][1]
self[i] = {ip1 > ip2 and ip2 or ip1, self[pos][2]}
self:remove(pos)
pos = pos - 1
if pos <= 1 then
break
end
end
pos = pos - 1
end
end
--------------------------------------------------------------------------------
-- IPCollection class
-- Holds a list of IP addresses/subnets. Used internally.
-- Each address/subnet has the same version (either IPv4 or IPv6).
--------------------------------------------------------------------------------
local IPCollection = {}
IPCollection.__index = IPCollection
function IPCollection.new(version)
assert(
version == V4 or version == V6,
'IPCollection.new called with an invalid version'
)
local obj = {
version = version, -- V4 or V6
addresses = Collection.new(), -- valid IP addresses
subnets = Collection.new(), -- valid subnets
omitted = Collection.new(), -- not-quite valid strings
}
return obj
end
function IPCollection:getVersion()
-- Return a string with the IP version of addresses in this collection.
return self.version
end
function IPCollection:_store(hit, stripColons)
local maker, location
if hit:find('/', 1, true) then
maker = Subnet.new
location = self.subnets
else
maker = IPAddress.new
location = self.addresses
end
local success, obj = pcall(maker, hit)
if success then
location:add(obj)
else
if stripColons then
local colons, hit = hit:match('^(:*)(.*)')
if colons ~= '' then
self:_store(hit)
return
end
end
self.omitted:add(hit)
end
end
function IPCollection:_assertVersion(version, msg)
if self.version ~= version then
error(msg, 3)
end
end
function IPCollection:addIP(ip)
local tp = type(ip)
if tp == 'string' then
ip = makeIPAddress(ip)
elseif tp == 'table' then
validateIPAddress('addIP', 1, ip)
else
checkTypeMulti('addIP', 1, ip, {'string', 'table'})
end
self:_assertVersion(ip:getVersion(), 'addIP called with incorrect IP version')
self.addresses:add(ip)
return self
end
function IPCollection:addSubnet(subnet)
local tp = type(subnet)
if tp == 'string' then
subnet = makeSubnet(subnet)
elseif tp == 'table' then
validateSubnet('addSubnet', 1, subnet)
else
checkTypeMulti('addSubnet', 1, subnet, {'string', 'table'})
end
self:_assertVersion(subnet:getVersion(), 'addSubnet called with incorrect subnet version')
self.subnets:add(subnet)
return self
end
function IPCollection:containsIP(ip)
-- Return true, obj if ip is in this collection,
-- where obj is the first IPAddress or Subnet with the ip.
-- Otherwise, return false.
local tp = type(ip)
if tp == 'string' then
ip = makeIPAddress(ip)
elseif tp == 'table' then
validateIPAddress('containsIP', 1, ip)
else
checkTypeMulti('containsIP', 1, ip, {'string', 'table'})
end
if self:getVersion() == ip:getVersion() then
for _, item in ipairs(self.addresses) do
if item == ip then
return true, item
end
end
for _, item in ipairs(self.subnets) do
if item:containsIP(ip) then
return true, item
end
end
end
return false
end
function IPCollection:getRanges()
-- Return a sorted table of IP pairs equivalent to the collection.
-- Each IP pair is a table representing a contiguous range of
-- IP addresses from pair[1] to pair[2] inclusive (IPAddress objects).
local ranges = Ranges.new()
for _, item in ipairs(self.addresses) do
ranges:add(item)
end
for _, item in ipairs(self.subnets) do
ranges:add(item:getPrefix(), item:getHighestIP())
end
ranges:merge()
ranges:deobjectify()
return ranges
end
function IPCollection:overlapsSubnet(subnet)
-- Return true, obj if subnet overlaps this collection,
-- where obj is the first IPAddress or Subnet overlapping the subnet.
-- Otherwise, return false.
local tp = type(subnet)
if tp == 'string' then
subnet = makeSubnet(subnet)
elseif tp == 'table' then
validateSubnet('overlapsSubnet', 1, subnet)
else
checkTypeMulti('overlapsSubnet', 1, subnet, {'string', 'table'})
end
if self:getVersion() == subnet:getVersion() then
for _, item in ipairs(self.addresses) do
if subnet:containsIP(item) then
return true, item
end
end
for _, item in ipairs(self.subnets) do
if subnet:overlapsSubnet(item) then
return true, item
end
end
end
return false
end
--------------------------------------------------------------------------------
-- IPv4Collection class
-- Holds a list of IPv4 addresses/subnets.
--------------------------------------------------------------------------------
local IPv4Collection = setmetatable({}, IPCollection)
IPv4Collection.__index = IPv4Collection
function IPv4Collection.new()
return setmetatable(IPCollection.new(V4), IPv4Collection)
end
function IPv4Collection:addFromString(text)
-- Extract any IPv4 addresses or CIDR subnets from given text.
checkType('addFromString', 1, text, 'string')
text = text:gsub('[:!"#&\'()+,%-;<=>?[%]_{|}]', ' ')
for hit in text:gmatch('%S+') do
if hit:match('^%d+%.%d+[%.%d/]+$') then
local _, n = hit:gsub('%.', '.')
if n >= 3 then
self:_store(hit)
end
end
end
return self
end
--------------------------------------------------------------------------------
-- IPv6Collection class
-- Holds a list of IPv6 addresses/subnets.
--------------------------------------------------------------------------------
local IPv6Collection = setmetatable({}, IPCollection)
IPv6Collection.__index = IPv6Collection
do
-- Private static methods
local function isCollectionObject(val)
-- Return true if val is probably derived from an IPCollection object,
-- otherwise return false.
if type(val) == 'table' then
local mt = getmetatable(val)
if mt == IPv4Collection or mt == IPv6Collection then
return true
end
end
return false
end
validateCollection = makeValidationFunction('IPCollection', isCollectionObject)
function IPv6Collection.new()
return setmetatable(IPCollection.new(V6), IPv6Collection)
end
function IPv6Collection:addFromString(text)
-- Extract any IPv6 addresses or CIDR subnets from given text.
-- Want to accept all valid IPv6 despite the fact that addresses used
-- are unlikely to start with ':'.
-- Also want to be able to parse arbitrary wikitext which might use
-- colons for indenting.
-- Therefore, if an address at the start of a line is valid, use it;
-- otherwise strip any leading colons and try again.
checkType('addFromString', 1, text, 'string')
for line in string.gmatch(text .. '\n', '[\t ]*(.-)[\t\r ]*\n') do
line = line:gsub('[!"#&\'()+,%-;<=>?[%]_{|}]', ' ')
for position, hit in line:gmatch('()(%S+)') do
local ip = hit:match('^([:%x]+)/?%d*$')
if ip then
local _, n = ip:gsub(':', ':')
if n >= 2 then
self:_store(hit, position == 1)
end
end
end
end
return self
end
end
return {
IPAddress = IPAddress,
Subnet = Subnet,
IPv4Collection = IPv4Collection,
IPv6Collection = IPv6Collection,
}
4w39co69exnm7uhqtjiyj7mfhjsv3zc
Bản mẫu:Blocked text/chỗ thử
10
72204
205224
2026-05-09T10:43:44Z
Hà Nội Bot
20162
Tạo phiên bản
205224
wikitext
text/x-wiki
__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{thay thế|(userorip) này đã bị [[Wikipedia:Quy định cấm thành viên|cấm]] ''sửa đổi'' tại Wikisource.|(userorip)|{{#if:{{#invoke:IPAddress|isIpOrRange|}}|Địa chỉ IP|Tài khoản}}}}'''</span><br/><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng ''đọc'' các trang Wikisource của bạn.</span></div>{{#if:||
{{#if:{{#invoke:IPAddress|isIpOrRange|}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số tác vụ cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những thành viên khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:|<div class="paragraphbreak" style="margin-top:0.5em"></div>
}}
{{#if:{{#invoke:IPAddress|isIpOrRange|}}|Địa chỉ IP hoặc dải IP|Tài khoản}} đã bị [[Wikisource:Quy định cấm|cấm]] bởi vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
</div>
{{#if:|Lệnh cấm này {{#if:|có hiệu lực là và}} sẽ {{#ifeq:|{{int:infiniteblock}}|không hết hạn|hết hạn vào }}{{#if:|, ID cấm là #}}.}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/|gửi thư]] cho bảo quản viên và các thành viên khác.
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[Wikisource:Quy định cấm|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.
</div>
{{#if:|Các liên kết hữu ích khác: [[]] {{#if:|· [[{{{usefullink2}}}]]}} {{#if:|· [[{{{usefullink3}}}]]}} {{#if:|· [[{{{usefullink4}}}]]}} {{#if:|· [[{{{usefullink5}}}]]}} {{#if:|· [[{{{usefullink6}}}]]}} {{#if:|· [[{{{usefullink7}}}]]}} {{#if:|· [[{{{usefullink8}}}]]}} {{#if:|· [[{{{usefullink9}}}]]}}}}
</div>
gcdaamnunjccfwhqaq98e7s19pv0bon
205225
205224
2026-05-09T10:44:24Z
Hà Nội Bot
20162
lỗi sai
205225
wikitext
text/x-wiki
<includeonly>__NOEDITSECTION____NOTOC__
<div id="mw-blocked-text" style="border: 1px solid #AAA; background:ivory; padding: 1.5em; width: 100%; box-sizing: border-box;">
<div style="text-align: center;"><span style="font-size: 26px;">[[File:Stop hand nuvola.svg|50px|link=|alt=]]''' {{thay thế|{{{blockheader|(userorip) này đã bị [[Wikipedia:Quy định cấm thành viên|cấm]] ''sửa đổi'' tại Wikisource.}}}|(userorip)|{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP|Tài khoản}}}}'''</span><br/><span style="font-size: 18px;">Điều này không làm ảnh hưởng đến khả năng {{{notblocked|''đọc'' các trang Wikisource}}} của bạn.</span></div>{{#if:{{{noipmessage|}}}||
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>'''Hầu hết những người nhìn thấy thông báo này không làm gì sai.''' Một số tác vụ cấm hạn chế sửa đổi từ những nhà cung cấp dịch vụ hoặc công ty viễn thông cụ thể do lạm dụng hoặc phá hoại gần đây, ảnh hưởng tới những thành viên khác không liên quan đến sự lạm dụng ấy. Xem bên dưới nếu bạn tin rằng bạn không làm gì sai.<div class="paragraphbreak" style="margin-top:0.5em"></div>}}
}}{{#if:{{{opener|}}}|<div class="paragraphbreak" style="margin-top:0.5em"></div>
{{{opener|}}}
}}
{{#if:{{#invoke:IPAddress|isIpOrRange|{{{7|}}}}}|Địa chỉ IP hoặc dải IP|Tài khoản}} {{{7|}}} đã bị [[Wikisource:Quy định cấm|cấm]] {{{descriptor|}}} bởi {{{1|}}} vì (những) lý do sau:
<div style="padding:10px; background:white; border:1px #666 solid;">
{{{2|}}}
</div>
{{#if:{{{6|}}}|Lệnh cấm này {{#if:{{{8|}}}|có hiệu lực là {{{8|}}}và}} sẽ {{#ifeq:{{{6|}}}|{{int:infiniteblock}}|không hết hạn|hết hạn vào {{{6|}}}}}{{#if:{{{blockid|}}}|, ID cấm là #{{{5|}}}}}.}}
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{closer|Ngay cả khi bị cấm, bạn ''thường'' vẫn sẽ có thể sửa đổi [[Đặc biệt:Thảo luận tôi|trang thảo luận thành viên]] của bạn và [[Đặc biệt:Gửi thư/{{{4|}}}|gửi thư]] cho bảo quản viên và các thành viên khác.}}}
</div>
<div class="paragraphbreak" style="margin-top:0.5em"></div><div style="font-size: 16px;">
{{{appealinfo|Để biết thêm thông tin về cách thực hiện, vui lòng đọc '''[[Wikisource:Không proxy mở#Quy định|các câu hỏi thường gặp dành cho người bị cấm]]''' và [[Wikisource:Không proxy mở|quy định chống lại quyết định cấm]]. [[Wikisource:Quy định cấm|Hướng dẫn chống lại quyết định cấm]] này cũng có thể hữu ích.}}}
</div>
{{#if:{{{usefullink1|}}}|Các liên kết hữu ích khác: [[{{{usefullink1|}}}]] {{#if:{{{usefullink2|}}}|· [[{{{usefullink2}}}]]}} {{#if:{{{usefullink3|}}}|· [[{{{usefullink3}}}]]}} {{#if:{{{usefullink4|}}}|· [[{{{usefullink4}}}]]}} {{#if:{{{usefullink5|}}}|· [[{{{usefullink5}}}]]}} {{#if:{{{usefullink6|}}}|· [[{{{usefullink6}}}]]}} {{#if:{{{usefullink7|}}}|· [[{{{usefullink7}}}]]}} {{#if:{{{usefullink8|}}}|· [[{{{usefullink8}}}]]}} {{#if:{{{usefullink9|}}}|· [[{{{usefullink9}}}]]}}}}
</div></includeonly>
<noinclude>{{Tài liệu}}</noinclude>
bt0jb6jsvv2sjf8sk0c73n6g4h5w3uf
Bản mẫu:Test case
10
72205
205226
2026-05-09T10:48:07Z
Hà Nội Bot
20162
[[w:WP:TTL|←]]Trang mới: “<includeonly>{{#gọi:Template test case|main}}</includeonly><noinclude> {{Tài liệu}} <!-- Categories go on the /doc subpage and interwikis go on Wikidata. --> </noinclude>”
205226
wikitext
text/x-wiki
<includeonly>{{#gọi:Template test case|main}}</includeonly><noinclude>
{{Tài liệu}}
<!-- Categories go on the /doc subpage and interwikis go on Wikidata. -->
</noinclude>
gwde97eotfev6t5tkfop2l3jjwbzd6n
Mô đun:Template test case
828
72206
205227
2026-05-09T10:49:14Z
Hà Nội Bot
20162
[[w:WP:TTL|←]]Trang mới: “--[[ A module for generating test case templates. This module incorporates code from the English Wikipedia's "Testcase table" module,[1] written by Frietjes [2] with contributions by Mr. Stradivarius [3] and Jackmcbarn,[4] and the English Wikipedia's "Testcase rows" module,[5] written by Mr. Stradivarius. The "Testcase table" and "Testcase rows" modules are released under the CC BY-SA 3.0 License [6] and the GFDL.[7] License: CC…”
205227
Scribunto
text/plain
--[[
A module for generating test case templates.
This module incorporates code from the English Wikipedia's "Testcase table"
module,[1] written by Frietjes [2] with contributions by Mr. Stradivarius [3]
and Jackmcbarn,[4] and the English Wikipedia's "Testcase rows" module,[5]
written by Mr. Stradivarius.
The "Testcase table" and "Testcase rows" modules are released under the
CC BY-SA 3.0 License [6] and the GFDL.[7]
License: CC BY-SA 3.0 and the GFDL
Author: Mr. Stradivarius
[1] https://en.wikipedia.org/wiki/Module:Testcase_table
[2] https://en.wikipedia.org/wiki/User:Frietjes
[3] https://en.wikipedia.org/wiki/User:Mr._Stradivarius
[4] https://en.wikipedia.org/wiki/User:Jackmcbarn
[5] https://en.wikipedia.org/wiki/Module:Testcase_rows
[6] https://en.wikipedia.org/wiki/Wikipedia:Text_of_Creative_Commons_Attribution-ShareAlike_3.0_Unported_License
[7] https://en.wikipedia.org/wiki/Wikipedia:Text_of_the_GNU_Free_Documentation_License
]]
-- Load required modules
local yesno = require('Module:Yesno')
-- Set constants
local DATA_MODULE = 'Module:Template test case/data'
-------------------------------------------------------------------------------
-- Shared methods
-------------------------------------------------------------------------------
local function message(self, key, ...)
-- This method is added to classes that need to deal with messages from the
-- config module.
local msg = self.cfg.msg[key]
if select(1, ...) then
return mw.message.newRawMessage(msg, ...):plain()
else
return msg
end
end
-------------------------------------------------------------------------------
-- Template class
-------------------------------------------------------------------------------
local Template = {}
Template.memoizedMethods = {
-- Names of methods to be memoized in each object. This table should only
-- hold methods with no parameters.
getFullPage = true,
getName = true,
makeHeader = true,
getOutput = true
}
function Template.new(invocationObj, options)
local obj = {}
-- Set input
for k, v in pairs(options or {}) do
if not Template[k] then
obj[k] = v
end
end
obj._invocation = invocationObj
-- Validate input
if not obj.template and not obj.title then
error('không có bản mẫu hoặc tiêu đề được định rõ', 2)
end
-- Memoize expensive method calls
local memoFuncs = {}
return setmetatable(obj, {
__index = function (t, key)
if Template.memoizedMethods[key] then
local func = memoFuncs[key]
if not func then
local val = Template[key](t)
func = function () return val end
memoFuncs[key] = func
end
return func
else
return Template[key]
end
end
})
end
function Template:getFullPage()
if not self.template then
return self.title.prefixedText
elseif self.template:sub(1, 7) == '#invoke' then
return 'Module' .. self.template:sub(8):gsub('|.*', '')
else
local strippedTemplate, hasColon = self.template:gsub('^:', '', 1)
hasColon = hasColon > 0
local ns = strippedTemplate:match('^(.-):')
ns = ns and mw.site.namespaces[ns]
if ns then
return strippedTemplate
elseif hasColon then
return strippedTemplate -- Main namespace
else
return mw.site.namespaces[10].name .. ':' .. strippedTemplate
end
end
end
function Template:getName()
if self.template then
return self.template
else
return require('Module:Template invocation').name(self.title)
end
end
function Template:makeLink(display)
if display then
return string.format('[[:%s|%s]]', self:getFullPage(), display)
else
return string.format('[[:%s]]', self:getFullPage())
end
end
function Template:makeBraceLink(display)
display = display or self:getName()
local link = self:makeLink(display)
return mw.text.nowiki('{{') .. link .. mw.text.nowiki('}}')
end
function Template:makeHeader()
return self.heading or self:makeBraceLink()
end
function Template:getInvocation(format)
local invocation = self._invocation:getInvocation{
template = self:getName(),
requireMagicWord = self.requireMagicWord,
}
if format == 'code' then
invocation = '<code>' .. mw.text.nowiki(invocation) .. '</code>'
elseif format == 'kbd' then
invocation = '<kbd>' .. mw.text.nowiki(invocation) .. '</kbd>'
elseif format == 'plain' then
invocation = mw.text.nowiki(invocation)
else
-- Default is pre tags
invocation = mw.text.encode(invocation, '&')
invocation = '<pre style="white-space: pre-wrap;">' .. invocation .. '</pre>'
invocation = mw.getCurrentFrame():preprocess(invocation)
end
return invocation
end
function Template:getOutput()
local protect = require('Module:Protect')
-- calling self._invocation:getOutput{...}
return protect(self._invocation.getOutput)(self._invocation, {
template = self:getName(),
requireMagicWord = self.requireMagicWord,
})
end
-------------------------------------------------------------------------------
-- TestCase class
-------------------------------------------------------------------------------
local TestCase = {}
TestCase.__index = TestCase
TestCase.message = message -- add the message method
TestCase.renderMethods = {
-- Keys in this table are values of the "format" option, values are the
-- method for rendering that format.
columns = 'renderColumns',
rows = 'renderRows',
tablerows = 'renderRows',
inline = 'renderInline',
cells = 'renderCells',
default = 'renderDefault'
}
function TestCase.new(invocationObj, options, cfg)
local obj = setmetatable({}, TestCase)
obj.cfg = cfg
-- Separate general options from template options. Template options are
-- numbered, whereas general options are not.
local generalOptions, templateOptions = {}, {}
for k, v in pairs(options) do
local prefix, num
if type(k) == 'string' then
prefix, num = k:match('^(.-)([1-9][0-9]*)$')
end
if prefix then
num = tonumber(num)
templateOptions[num] = templateOptions[num] or {}
templateOptions[num][prefix] = v
else
generalOptions[k] = v
end
end
-- Set general options
generalOptions.showcode = yesno(generalOptions.showcode)
generalOptions.showheader = yesno(generalOptions.showheader) ~= false
generalOptions.showcaption = yesno(generalOptions.showcaption) ~= false
generalOptions.collapsible = yesno(generalOptions.collapsible)
generalOptions.notcollapsed = yesno(generalOptions.notcollapsed)
generalOptions.wantdiff = yesno(generalOptions.wantdiff)
obj.options = generalOptions
-- Preprocess template args
for num, t in pairs(templateOptions) do
if t.showtemplate ~= nil then
t.showtemplate = yesno(t.showtemplate)
end
end
-- Set up first two template options tables, so that if only the
-- "template3" is specified it isn't made the first template when the
-- the table options array is compressed.
templateOptions[1] = templateOptions[1] or {}
templateOptions[2] = templateOptions[2] or {}
-- Allow the "template" option to override the "template1" option for
-- backwards compatibility with [[Module:Testcase table]].
if generalOptions.template then
templateOptions[1].template = generalOptions.template
end
-- Add default template options
if templateOptions[1].template and not templateOptions[2].template then
templateOptions[2].template = templateOptions[1].template ..
'/' .. obj.cfg.sandboxSubpage
end
if not templateOptions[1].template then
templateOptions[1].title = mw.title.getCurrentTitle().basePageTitle
end
if not templateOptions[2].template then
templateOptions[2].title = templateOptions[1].title:subPageTitle(
obj.cfg.sandboxSubpage
)
end
-- Remove template options for any templates where the showtemplate
-- argument is false. This prevents any output for that template.
for num, t in pairs(templateOptions) do
if t.showtemplate == false then
templateOptions[num] = nil
end
end
-- Check for missing template names.
for num, t in pairs(templateOptions) do
if not t.template and not t.title then
error(obj:message(
'missing-template-option-error',
num, num
), 2)
end
end
-- Compress templateOptions table so we can iterate over it with ipairs.
templateOptions = (function (t)
local nums = {}
for num in pairs(t) do
nums[#nums + 1] = num
end
table.sort(nums)
local ret = {}
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end)(templateOptions)
-- Don't require the __TEMPLATENAME__ magic word for nowiki invocations if
-- there is only one template being output.
if #templateOptions <= 1 then
templateOptions[1].requireMagicWord = false
end
mw.logObject(templateOptions)
-- Make the template objects
obj.templates = {}
for i, options in ipairs(templateOptions) do
table.insert(obj.templates, Template.new(invocationObj, options))
end
-- Add tracking categories. At the moment we are only tracking templates
-- that use any "heading" parameters or an "output" parameter.
obj.categories = {}
for k, v in pairs(options) do
if type(k) == 'string' and k:find('heading') then
obj.categories['Các trường hợp kiểm thử sử dụng các tham số phần mở đầu'] = true
elseif k == 'output' then
obj.categories['Các trường hợp kiểm thử sử dụng tham số đầu ra'] = true
end
end
return obj
end
function TestCase:getTemplateOutput(templateObj)
local output = templateObj:getOutput()
if self.options.resetRefs then
mw.getCurrentFrame():extensionTag('references')
end
return output
end
function TestCase:templateOutputIsEqual()
-- Returns a boolean showing whether all of the template outputs are equal.
-- The random parts of strip markers (see [[Help:Strip markers]]) are
-- removed before comparison. This means a strip marker can contain anything
-- and still be treated as equal, but it solves the problem of otherwise
-- identical wikitext not returning as exactly equal.
local function normaliseOutput(obj)
local out = obj:getOutput()
-- Remove the random parts from strip markers.
out = out:gsub('(\127[^\127]*UNIQ%-%-%l+%-)%x+(%-%-?QINU[^\127]*\127)', '%1%2')
return out
end
local firstOutput = normaliseOutput(self.templates[1])
for i = 2, #self.templates do
local output = normaliseOutput(self.templates[i])
if output ~= firstOutput then
return false
end
end
return true
end
function TestCase:makeCollapsible(s)
local title = self.options.title or self.templates[1]:makeHeader()
if self.options.titlecode then
title = self.templates[1]:getInvocation('kbd')
end
local isEqual = self:templateOutputIsEqual()
local root = mw.html.create('div')
root
:addClass('mw-collapsible')
:css('width', '100%')
:css('border', 'solid silver 1px')
:css('padding', '0.2em')
:css('clear', 'both')
:addClass(self.options.notcollapsed == false and 'mw-collapsed' or nil)
if self.options.wantdiff then
root
:tag('div')
:css('background-color', isEqual and 'yellow' or '#90a8ee')
:css('color', 'black')
:css('font-weight', 'bold')
:css('padding', '0.2em')
:wikitext(title)
:done()
else
if self.options.notcollapsed ~= true or false then
root
:addClass(isEqual and 'mw-collapsed' or nil)
end
root
:tag('div')
:css('background-color', isEqual and 'lightgreen' or 'yellow')
:css('color', 'black')
:css('font-weight', 'bold')
:css('padding', '0.2em')
:wikitext(title)
:done()
end
root
:tag('div')
:addClass('mw-collapsible-content')
:newline()
:wikitext(s)
:newline()
return tostring(root)
end
function TestCase:renderColumns()
local root = mw.html.create()
if self.options.showcode then
root
:wikitext(self.templates[1]:getInvocation())
:newline()
end
local tableroot = root:tag('table')
if self.options.showheader then
-- Caption
if self.options.showcaption then
tableroot
:addClass(self.options.class)
:cssText(self.options.style)
:tag('caption')
:wikitext(self.options.caption or self:message('columns-header'))
end
-- Headers
local headerRow = tableroot:tag('tr')
if self.options.rowheader then
-- rowheader is correct here. We need to add another th cell if
-- rowheader is set further down, even if heading0 is missing.
headerRow:tag('th'):wikitext(self.options.heading0)
end
local width
if #self.templates > 0 then
width = tostring(math.floor(100 / #self.templates)) .. '%'
else
width = '100%'
end
for i, obj in ipairs(self.templates) do
headerRow
:tag('th')
:css('width', width)
:wikitext(obj:makeHeader())
end
end
-- Row header
local dataRow = tableroot:tag('tr'):css('vertical-align', 'top')
if self.options.rowheader then
dataRow:tag('th')
:attr('scope', 'row')
:wikitext(self.options.rowheader)
end
-- Template output
for i, obj in ipairs(self.templates) do
if self.options.output == 'nowiki+' then
dataRow:tag('td')
:newline()
:wikitext(self.options.before)
:wikitext(self:getTemplateOutput(obj))
:wikitext(self.options.after)
:wikitext('<pre style="white-space: pre-wrap;">')
:wikitext(mw.text.nowiki(self.options.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
:wikitext('</pre>')
elseif self.options.output == 'nowiki' then
dataRow:tag('td')
:newline()
:wikitext(mw.text.nowiki(self.options.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
else
dataRow:tag('td')
:newline()
:wikitext(self.options.before)
:wikitext(self:getTemplateOutput(obj))
:wikitext(self.options.after)
end
end
return tostring(root)
end
function TestCase:renderRows()
local root = mw.html.create()
if self.options.showcode then
root
:wikitext(self.templates[1]:getInvocation())
:newline()
end
local tableroot = root:tag('table')
tableroot
:addClass(self.options.class)
:cssText(self.options.style)
if self.options.caption then
tableroot
:tag('caption')
:wikitext(self.options.caption)
end
for _, obj in ipairs(self.templates) do
local dataRow = tableroot:tag('tr')
-- Header
if self.options.showheader then
if self.options.format == 'tablerows' then
dataRow:tag('th')
:attr('scope', 'row')
:css('vertical-align', 'top')
:css('text-align', 'left')
:wikitext(obj:makeHeader())
dataRow:tag('td')
:css('vertical-align', 'top')
:css('padding', '0 1em')
:wikitext('→')
else
dataRow:tag('td')
:css('text-align', 'center')
:css('font-weight', 'bold')
:wikitext(obj:makeHeader())
dataRow = tableroot:tag('tr')
end
end
-- Template output
if self.options.output == 'nowiki+' then
dataRow:tag('td')
:newline()
:wikitext(self.options.before)
:wikitext(self:getTemplateOutput(obj))
:wikitext(self.options.after)
:wikitext('<pre style="white-space: pre-wrap;">')
:wikitext(mw.text.nowiki(self.options.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
:wikitext('</pre>')
elseif self.options.output == 'nowiki' then
dataRow:tag('td')
:newline()
:wikitext(mw.text.nowiki(self.options.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
else
dataRow:tag('td')
:newline()
:wikitext(self.options.before)
:wikitext(self:getTemplateOutput(obj))
:wikitext(self.options.after)
end
end
return tostring(root)
end
function TestCase:renderInline()
local arrow = mw.language.getContentLanguage():getArrow('forwards')
local ret = {}
for i, obj in ipairs(self.templates) do
local line = {}
line[#line + 1] = self.options.prefix or '* '
if self.options.showcode then
line[#line + 1] = obj:getInvocation('code')
line[#line + 1] = ' '
line[#line + 1] = arrow
line[#line + 1] = ' '
end
if self.options.output == 'nowiki+' then
line[#line + 1] = self.options.before or ""
line[#line + 1] = self:getTemplateOutput(obj)
line[#line + 1] = self.options.after or ""
line[#line + 1] = '<pre style="white-space: pre-wrap;">'
line[#line + 1] = mw.text.nowiki(self.options.before or "")
line[#line + 1] = mw.text.nowiki(self:getTemplateOutput(obj))
line[#line + 1] = mw.text.nowiki(self.options.after or "")
line[#line + 1] = '</pre>'
elseif self.options.output == 'nowiki' then
line[#line + 1] = mw.text.nowiki(self.options.before or "")
line[#line + 1] = mw.text.nowiki(self:getTemplateOutput(obj))
line[#line + 1] = mw.text.nowiki(self.options.after or "")
else
line[#line + 1] = self.options.before or ""
line[#line + 1] = self:getTemplateOutput(obj)
line[#line + 1] = self.options.after or ""
end
ret[#ret + 1] = table.concat(line)
end
if self.options.addline then
local line = {}
line[#line + 1] = self.options.prefix or '* '
line[#line + 1] = self.options.addline
ret[#ret + 1] = table.concat(line)
end
return table.concat(ret, '\n')
end
function TestCase:renderCells()
local root = mw.html.create()
local dataRow = root:tag('tr')
dataRow
:css('vertical-align', 'top')
:addClass(self.options.class)
:cssText(self.options.style)
-- Row header
if self.options.rowheader then
dataRow:tag('th')
:attr('scope', 'row')
:newline()
:wikitext(self.options.rowheader or self:message('row-header'))
end
-- Caption
if self.options.showcaption then
dataRow:tag('th')
:attr('scope', 'row')
:newline()
:wikitext(self.options.caption or self:message('columns-header'))
end
-- Show code
if self.options.showcode then
dataRow:tag('td')
:newline()
:wikitext(self:getInvocation('code'))
end
-- Template output
for i, obj in ipairs(self.templates) do
if self.options.output == 'nowiki+' then
dataRow:tag('td')
:newline()
:wikitext(self.options.before)
:wikitext(self:getTemplateOutput(obj))
:wikitext(self.options.after)
:wikitext('<pre style="white-space: pre-wrap;">')
:wikitext(mw.text.nowiki(self.options.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
:wikitext('</pre>')
elseif self.options.output == 'nowiki' then
dataRow:tag('td')
:newline()
:wikitext(mw.text.nowiki(self.options.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
else
dataRow:tag('td')
:newline()
:wikitext(self.options.before)
:wikitext(self:getTemplateOutput(obj))
:wikitext(self.options.after)
end
end
return tostring(root)
end
function TestCase:renderDefault()
local ret = {}
if self.options.showcode then
ret[#ret + 1] = self.templates[1]:getInvocation()
end
for i, obj in ipairs(self.templates) do
ret[#ret + 1] = '<div style="clear: both;"></div>'
if self.options.showheader then
ret[#ret + 1] = obj:makeHeader()
end
if self.options.output == 'nowiki+' then
ret[#ret + 1] = (self.options.before or "") ..
self:getTemplateOutput(obj) ..
(self.options.after or "") ..
'<pre style="white-space: pre-wrap;">' ..
mw.text.nowiki(self.options.before or "") ..
mw.text.nowiki(self:getTemplateOutput(obj)) ..
mw.text.nowiki(self.options.after or "") .. '</pre>'
elseif self.options.output == 'nowiki' then
ret[#ret + 1] = mw.text.nowiki(self.options.before or "") ..
mw.text.nowiki(self:getTemplateOutput(obj)) ..
mw.text.nowiki(self.options.after or "")
else
ret[#ret + 1] = (self.options.before or "") ..
self:getTemplateOutput(obj) ..
(self.options.after or "")
end
end
return table.concat(ret, '\n\n')
end
function TestCase:__tostring()
local format = self.options.format
local method = format and TestCase.renderMethods[format] or 'renderDefault'
local ret = self[method](self)
if self.options.collapsible then
ret = self:makeCollapsible(ret)
end
for cat in pairs(self.categories) do
ret = ret .. string.format('[[Thể loại:%s]]', cat)
end
return ret
end
-------------------------------------------------------------------------------
-- Nowiki invocation class
-------------------------------------------------------------------------------
local NowikiInvocation = {}
NowikiInvocation.__index = NowikiInvocation
NowikiInvocation.message = message -- Add the message method
function NowikiInvocation.new(invocation, cfg)
local obj = setmetatable({}, NowikiInvocation)
obj.cfg = cfg
invocation = mw.text.unstrip(invocation)
-- Decode HTML entities for <, >, and ". This means that HTML entities in
-- the original code must be escaped as e.g. &lt;, which is unfortunate,
-- but it is the best we can do as the distinction between <, >, " and <,
-- >, " is lost during the original nowiki operation.
invocation = invocation:gsub('<', '<')
invocation = invocation:gsub('>', '>')
invocation = invocation:gsub('"', '"')
obj.invocation = invocation
return obj
end
function NowikiInvocation:getInvocation(options)
local template = options.template:gsub('%%', '%%%%') -- Escape "%" with "%%"
local invocation, count = self.invocation:gsub(
self.cfg.templateNameMagicWordPattern,
template
)
if options.requireMagicWord ~= false and count < 1 then
error(self:message(
'nowiki-magic-word-error',
self.cfg.templateNameMagicWord
))
end
return invocation
end
function NowikiInvocation:getOutput(options)
local invocation = self:getInvocation(options)
return mw.getCurrentFrame():preprocess(invocation)
end
-------------------------------------------------------------------------------
-- Table invocation class
-------------------------------------------------------------------------------
local TableInvocation = {}
TableInvocation.__index = TableInvocation
TableInvocation.message = message -- Add the message method
function TableInvocation.new(invokeArgs, nowikiCode, cfg)
local obj = setmetatable({}, TableInvocation)
obj.cfg = cfg
obj.invokeArgs = invokeArgs
obj.code = nowikiCode
return obj
end
function TableInvocation:getInvocation(options)
if self.code then
local nowikiObj = NowikiInvocation.new(self.code, self.cfg)
return nowikiObj:getInvocation(options)
else
return require('Module:Template invocation').invocation(
options.template,
self.invokeArgs
)
end
end
function TableInvocation:getOutput(options)
if (options.template:sub(1, 7) == '#invoke') then
local moduleCall = mw.text.split(options.template, '|', true)
local args = mw.clone(self.invokeArgs)
table.insert(args, 1, moduleCall[2])
return mw.getCurrentFrame():callParserFunction(moduleCall[1], args)
end
return mw.getCurrentFrame():expandTemplate{
title = options.template,
args = self.invokeArgs
}
end
-------------------------------------------------------------------------------
-- Bridge functions
--
-- These functions translate template arguments into forms that can be accepted
-- by the different classes, and return the results.
-------------------------------------------------------------------------------
local bridge = {}
function bridge.table(args, cfg)
cfg = cfg or mw.loadData(DATA_MODULE)
local options, invokeArgs = {}, {}
for k, v in pairs(args) do
local optionKey = type(k) == 'string' and k:match('^_(.*)$')
if optionKey then
if type(v) == 'string' then
v = v:match('^%s*(.-)%s*$') -- trim whitespace
end
if v ~= '' then
options[optionKey] = v
end
else
invokeArgs[k] = v
end
end
-- Allow passing a nowiki invocation as an option. While this means users
-- have to pass in the code twice, whitespace is preserved and < etc.
-- will work as intended.
local nowikiCode = options.code
options.code = nil
local invocationObj = TableInvocation.new(invokeArgs, nowikiCode, cfg)
local testCaseObj = TestCase.new(invocationObj, options, cfg)
return tostring(testCaseObj)
end
function bridge.nowiki(args, cfg)
cfg = cfg or mw.loadData(DATA_MODULE)
-- Convert args beginning with _ for consistency with the normal bridge
local newArgs = {}
for k, v in pairs(args) do
local normalName = type(k) == "string" and string.match(k, "^_(.*)$")
if normalName then
newArgs[normalName] = v
else
newArgs[k] = v
end
end
local code = newArgs.code or newArgs[1]
local invocationObj = NowikiInvocation.new(code, cfg)
newArgs.code = nil
newArgs[1] = nil
-- Assume we want to see the code as we already passed it in.
newArgs.showcode = newArgs.showcode or true
local testCaseObj = TestCase.new(invocationObj, newArgs, cfg)
return tostring(testCaseObj)
end
-------------------------------------------------------------------------------
-- Exports
-------------------------------------------------------------------------------
local p = {}
function p.main(frame, cfg)
cfg = cfg or mw.loadData(DATA_MODULE)
-- Load the wrapper config, if any.
local wrapperConfig
if frame.getParent then
local title = frame:getParent():getTitle()
local template = title:gsub(cfg.sandboxSubpagePattern, '')
wrapperConfig = cfg.wrappers[template]
end
-- Work out the function we will call, use it to generate the config for
-- Module:Arguments, and use Module:Arguments to find the arguments passed
-- by the user.
local func = wrapperConfig and wrapperConfig.func or 'table'
local userArgs = require('Module:Arguments').getArgs(frame, {
parentOnly = wrapperConfig,
frameOnly = not wrapperConfig,
trim = func ~= 'table',
removeBlanks = func ~= 'table'
})
-- Get default args and build the args table. User-specified args overwrite
-- default args.
local defaultArgs = wrapperConfig and wrapperConfig.args or {}
local args = {}
for k, v in pairs(defaultArgs) do
args[k] = v
end
for k, v in pairs(userArgs) do
args[k] = v
end
return bridge[func](args, cfg)
end
function p._exportClasses() -- For testing
return {
Template = Template,
TestCase = TestCase,
NowikiInvocation = NowikiInvocation,
TableInvocation = TableInvocation
}
end
return p
d1d4eqrd9uxqj658r5ou4xf68rt0ft8
Mô đun:Template test case/data
828
72207
205228
2026-05-09T10:49:56Z
Hà Nội Bot
20162
[[w:WP:TTL|←]]Trang mới: “-- This module processes configuration data for use in -- [[Mô đun:Template test case]]. It is loaded from the main module with -- mw.loadData. local cfg = require('Mô đun:Template test case/config') local function escapePattern(s) s = s:gsub('%p', '%%%0') return s end -- Escape config items that need to be used as patterns. Doing it here is more -- efficient, as mw.loadData saves them from having to be computed for every -- test case on a page. c…”
205228
Scribunto
text/plain
-- This module processes configuration data for use in
-- [[Mô đun:Template test case]]. It is loaded from the main module with
-- mw.loadData.
local cfg = require('Mô đun:Template test case/config')
local function escapePattern(s)
s = s:gsub('%p', '%%%0')
return s
end
-- Escape config items that need to be used as patterns. Doing it here is more
-- efficient, as mw.loadData saves them from having to be computed for every
-- test case on a page.
cfg.templateNameMagicWordPattern = escapePattern(cfg.templateNameMagicWord)
cfg.sandboxSubpagePattern = '/' .. escapePattern(cfg.sandboxSubpage) .. '$'
return cfg
mnhci00d4f65cojga1ryeu621cw42bb
Mô đun:Template test case/config
828
72208
205229
2026-05-09T10:50:24Z
Hà Nội Bot
20162
[[w:WP:TTL|←]]Trang mới: “------------------------------------------------------------------------------- -- Mô đun:Template test case/config -- This module holds configuration data for [[Mô đun:Template test case]]. ------------------------------------------------------------------------------- return { ------------------------------------------------------------------------------- -- Options ----------------------------------------------------------------…”
205229
Scribunto
text/plain
-------------------------------------------------------------------------------
-- Mô đun:Template test case/config
-- This module holds configuration data for [[Mô đun:Template test case]].
-------------------------------------------------------------------------------
return {
-------------------------------------------------------------------------------
-- Options
-------------------------------------------------------------------------------
-- The magic word used in place of the template name when making nowiki
-- invocations.
templateNameMagicWord = '__TEMPLATENAME__',
-- The subpage that sandboxes are typically stored on. Used when loading
-- wrapper template config and when guessing the sandbox template name.
sandboxSubpage = 'sandbox',
-------------------------------------------------------------------------------
-- Messages
-------------------------------------------------------------------------------
msg = {
-- The default header for test cases rendered in columns.
['columns-header'] = 'So sánh hai bên',
-- The error message to use if a templaten option is missing.
-- $1 - the number of the missing template option.
['missing-template-option-error'] = "one or more options ending in '$1' " ..
"were detected, but no 'template$1' option was found",
-- The error message to use if a nowiki invocation is used but the template
-- name magic word is not found.
-- $1 - the value of the template name magic word
['nowiki-magic-word-error'] = "the template invocation must include '$1' in " ..
"place of the template name",
},
-------------------------------------------------------------------------------
-- Wrapper template config.
-- The wrapper template config is a table with wrapper template names as keys,
-- and subtables containing two fields:
-- func - the function name to be used with that template. This must be a
-- function exported by the main module. This is optional: the default
-- value is "table".
-- args - a table of default arguments to be used with that template. This is
-- is optional.
-------------------------------------------------------------------------------
wrappers = {
['Bản mẫu:Test case'] = {},
['Bản mẫu:Testcase table'] = {
args = {_format = 'columns'}
},
['Bản mẫu:Testcase rows'] = {
args = {_format = 'rows'}
},
['Bản mẫu:Test case nowiki'] = {
func = 'nowiki'
},
['Bản mẫu:Nowiki template demo'] = {
func = 'nowiki',
args = {showheader = false, showtemplate2 = false}
},
['Bản mẫu:Collapsible test case'] = {
args = {_collapsible = true}
},
['Bản mẫu:Collapsible 2 test case'] = {
args = {_collapsible = true, _wantdiff = true}
},
['Bản mẫu:Inline test case'] = {
args = {_format = 'inline', _showcode = true}
},
},
-------------------------------------------------------------------------------
-- End config
-------------------------------------------------------------------------------
}
m58vic3vu468gjjxgdimb9c97yyxicl
Mô đun:Template invocation
828
72209
205230
2026-05-09T10:51:19Z
Hà Nội Bot
20162
[[w:WP:TTL|←]]Trang mới: “-- This module provides functions for making MediaWiki template invocations. local checkType = require('libraryUtil').checkType local p = {} ------------------------------------------------------------------------ -- Name: p.name -- Purpose: Find a template invocation name from a page name or a -- mw.title object. -- Description: This function detects whether a string or a mw.title -- object has been passed…”
205230
Scribunto
text/plain
-- This module provides functions for making MediaWiki template invocations.
local checkType = require('libraryUtil').checkType
local p = {}
------------------------------------------------------------------------
-- Name: p.name
-- Purpose: Find a template invocation name from a page name or a
-- mw.title object.
-- Description: This function detects whether a string or a mw.title
-- object has been passed in, and uses that to find a
-- template name as it is used in template invocations.
-- Parameters: title - full page name or mw.title object for the
-- template (string or mw.title object)
-- Returns: String
------------------------------------------------------------------------
function p.name(title)
if type(title) == 'string' then
title = mw.title.new(title)
if not title or #title.prefixedText == 0 or #title.interwiki > 0 then
error("tiêu đề không hợp lệ trong tham số #1 của hàm 'name'", 2)
end
elseif type(title) ~= 'table' or type(title.getContent) ~= 'function' then
error("tham số #1 của hàm 'name' phải có một chuỗi hoặc một đối tượng mw.title", 2)
end
if title.namespace == 10 then
local text = title.text
local check = mw.title.new(text, 10)
-- Exclude the prefix, unless we have something like "Template:Category:Foo", which can't be abbreviated to "Category:Foo".
return check and mw.title.equals(title, check) and text or title.prefixedText
elseif title.namespace == 0 then
return ':' .. title.prefixedText
else
return title.prefixedText
end
end
------------------------------------------------------------------------
-- Name: p.invocation
-- Purpose: Construct a MediaWiki template invocation.
-- Description: This function makes a template invocation from the
-- name and the arguments given. Note that it isn't
-- perfect: we have no way of knowing what whitespace was
-- in the original invocation, the named parameters will be
-- alphabetically sorted, and any parameters with duplicate keys
-- will be removed.
-- Parameters: name - the template name, formatted as it will appear
-- in the invocation. (string)
-- args - a table of template arguments. (table)
-- format - formatting options. (string, optional)
-- Set to "nowiki" to escape, curly braces, pipes and
-- equals signs with their HTML entities. The default
-- is unescaped.
-- Returns: String
------------------------------------------------------------------------
function p.invocation(name, args, format)
checkType('invocation', 1, name, 'string')
checkType('invocation', 2, args, 'table')
checkType('invocation', 3, format, 'string', true)
-- Validate the args table and make a copy to work from. We need to
-- make a copy of the table rather than just using the original, as
-- some of the values may be erased when building the invocation.
local invArgs = {}
for k, v in pairs(args) do
local typek = type(k)
local typev = type(v)
if typek ~= 'string' and typek ~= 'number'
or typev ~= 'string' and typev ~= 'number'
then
error("bảng đối số không hợp lệ trong tham số #2 của " ..
"'lời gọi' (khoá và giá trị phải là chuỗi hoặc số)", 2)
end
invArgs[k] = v
end
-- Get the separators to use.
local seps = {
openb = '{{',
closeb = '}}',
pipe = '|',
equals = '='
}
if format == 'nowiki' then
for k, v in pairs(seps) do
seps[k] = mw.text.nowiki(v)
end
end
-- Build the invocation body with numbered args first, then named.
local ret = {}
ret[#ret + 1] = seps.openb
ret[#ret + 1] = name
for k, v in ipairs(invArgs) do
if type(v) == 'string' and v:find('=', 1, true) then
-- Likely something like 1=foo=bar which needs to be displayed as a named arg.
else
ret[#ret + 1] = seps.pipe
ret[#ret + 1] = v
invArgs[k] = nil -- Erase the key so that we don't add the value twice
end
end
local keys = {} -- sort parameter list; better than arbitrary order
for k, _ in pairs(invArgs) do
keys[#keys + 1] = k
end
table.sort(keys,
function (a, b)
-- Sort with keys of type number first, then string.
if type(a) == type(b) then
return a < b
elseif type(a) == 'number' then
return true
end
end
)
local maybeSpace = '' -- First named parameter should not be separated by a space
for _, v in ipairs(keys) do -- Add named args based on sorted parameter list
ret[#ret + 1] = maybeSpace .. seps.pipe
ret[#ret + 1] = tostring(v)
ret[#ret + 1] = seps.equals
ret[#ret + 1] = invArgs[v]
maybeSpace = ' '
end
ret[#ret + 1] = seps.closeb
return table.concat(ret)
end
return p
hlwz6r70cdo674eu2xngxqemz6uq2ou
Mô đun:Protect
828
72210
205231
2026-05-09T10:51:43Z
Hà Nội Bot
20162
[[w:WP:TTL|←]]Trang mới: “-- This module provides functions for making MediaWiki template invocations. local checkType = require('libraryUtil').checkType local p = {} ------------------------------------------------------------------------ -- Name: p.name -- Purpose: Find a template invocation name from a page name or a -- mw.title object. -- Description: This function detects whether a string or a mw.title -- object has been passed…”
205231
Scribunto
text/plain
-- This module provides functions for making MediaWiki template invocations.
local checkType = require('libraryUtil').checkType
local p = {}
------------------------------------------------------------------------
-- Name: p.name
-- Purpose: Find a template invocation name from a page name or a
-- mw.title object.
-- Description: This function detects whether a string or a mw.title
-- object has been passed in, and uses that to find a
-- template name as it is used in template invocations.
-- Parameters: title - full page name or mw.title object for the
-- template (string or mw.title object)
-- Returns: String
------------------------------------------------------------------------
function p.name(title)
if type(title) == 'string' then
title = mw.title.new(title)
if not title or #title.prefixedText == 0 or #title.interwiki > 0 then
error("tiêu đề không hợp lệ trong tham số #1 của hàm 'name'", 2)
end
elseif type(title) ~= 'table' or type(title.getContent) ~= 'function' then
error("tham số #1 của hàm 'name' phải có một chuỗi hoặc một đối tượng mw.title", 2)
end
if title.namespace == 10 then
local text = title.text
local check = mw.title.new(text, 10)
-- Exclude the prefix, unless we have something like "Template:Category:Foo", which can't be abbreviated to "Category:Foo".
return check and mw.title.equals(title, check) and text or title.prefixedText
elseif title.namespace == 0 then
return ':' .. title.prefixedText
else
return title.prefixedText
end
end
------------------------------------------------------------------------
-- Name: p.invocation
-- Purpose: Construct a MediaWiki template invocation.
-- Description: This function makes a template invocation from the
-- name and the arguments given. Note that it isn't
-- perfect: we have no way of knowing what whitespace was
-- in the original invocation, the named parameters will be
-- alphabetically sorted, and any parameters with duplicate keys
-- will be removed.
-- Parameters: name - the template name, formatted as it will appear
-- in the invocation. (string)
-- args - a table of template arguments. (table)
-- format - formatting options. (string, optional)
-- Set to "nowiki" to escape, curly braces, pipes and
-- equals signs with their HTML entities. The default
-- is unescaped.
-- Returns: String
------------------------------------------------------------------------
function p.invocation(name, args, format)
checkType('invocation', 1, name, 'string')
checkType('invocation', 2, args, 'table')
checkType('invocation', 3, format, 'string', true)
-- Validate the args table and make a copy to work from. We need to
-- make a copy of the table rather than just using the original, as
-- some of the values may be erased when building the invocation.
local invArgs = {}
for k, v in pairs(args) do
local typek = type(k)
local typev = type(v)
if typek ~= 'string' and typek ~= 'number'
or typev ~= 'string' and typev ~= 'number'
then
error("bảng đối số không hợp lệ trong tham số #2 của " ..
"'lời gọi' (khoá và giá trị phải là chuỗi hoặc số)", 2)
end
invArgs[k] = v
end
-- Get the separators to use.
local seps = {
openb = '{{',
closeb = '}}',
pipe = '|',
equals = '='
}
if format == 'nowiki' then
for k, v in pairs(seps) do
seps[k] = mw.text.nowiki(v)
end
end
-- Build the invocation body with numbered args first, then named.
local ret = {}
ret[#ret + 1] = seps.openb
ret[#ret + 1] = name
for k, v in ipairs(invArgs) do
if type(v) == 'string' and v:find('=', 1, true) then
-- Likely something like 1=foo=bar which needs to be displayed as a named arg.
else
ret[#ret + 1] = seps.pipe
ret[#ret + 1] = v
invArgs[k] = nil -- Erase the key so that we don't add the value twice
end
end
local keys = {} -- sort parameter list; better than arbitrary order
for k, _ in pairs(invArgs) do
keys[#keys + 1] = k
end
table.sort(keys,
function (a, b)
-- Sort with keys of type number first, then string.
if type(a) == type(b) then
return a < b
elseif type(a) == 'number' then
return true
end
end
)
local maybeSpace = '' -- First named parameter should not be separated by a space
for _, v in ipairs(keys) do -- Add named args based on sorted parameter list
ret[#ret + 1] = maybeSpace .. seps.pipe
ret[#ret + 1] = tostring(v)
ret[#ret + 1] = seps.equals
ret[#ret + 1] = invArgs[v]
maybeSpace = ' '
end
ret[#ret + 1] = seps.closeb
return table.concat(ret)
end
return p
hlwz6r70cdo674eu2xngxqemz6uq2ou