Wikipedia
testwiki
https://test.wikipedia.org/wiki/Main_Page
MediaWiki 1.47.0-wmf.20
first-letter
Media
Special
Talk
User
User talk
Wikipedia
Wikipedia talk
File
File talk
MediaWiki
MediaWiki talk
Template
Template talk
Help
Help talk
Category
Category talk
Thread
Thread talk
Summary
Summary talk
Test namespace 1
Test namespace 1 talk
Test namespace 2
Test namespace 2 talk
Draft
Draft talk
Campaign
Campaign talk
TimedText
TimedText talk
Module
Module talk
SecurePoll
SecurePoll talk
Package
Package talk
CNBanner
CNBanner talk
Translations
Translations talk
Event
Event talk
Topic
Newsletter
Newsletter talk
Wikipedia:Test
4
71460
762122
762056
2026-09-17T22:50:24Z
~2026-49929-60
75678
/* Test */ Start
762122
wikitext
text/x-wiki
= Test =
917
Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control and until the 24 Restriction until no edits made all day, Most Edits made on 6/23, No New Episodes Released on 6/24, Use Account Sometimes.
2:6 — 8:27, 203 days, (8:28+ to fill out).
*8:28, 8:29, 8:30, 8:31, 9:1, (?)
*9:2, 9:3, 9:4, 9:5, 9:6, (?)
*9:7, 9:8 (?)
*9:9 (?)
*9:10 (?)
*9:11 (?)
*9:12 (?)
*9:13 (?)
*9:14 (9:15)
''9:16''
*202 6525, Pot with Fork and Spoon, Bags with Sunglasses.
*202 6526, Baskets, Tobacco Stuff or Socks.
*202 6527, Food Shopping like Cola Bottles, Cans, Cordial and Others.
*202 6528, Socks, Pairs of Shoes, Dressing Gowns.
*202 6529, Towels, Cubes with Things.
*202 6530, Cloths, Flowers Frisun or Soap.
*202 6531, Food Shopping like Party Pies, Waters and Others.
*202 6601, Pairs of Boots, Pillow or Podiatrist.
*202 6602, Plates or Pans, Grated Cheese or Baskets.
*202 6603, Forks, Pans and Other Kitchen Tools.
*202 6604, Cups, Cordial Jug or Strawberry Milk.
*202 6605, Food Shopping like Cans of Coca Cola, Waters, Cordials or Pile of Sauce.
*202 6606, Purses, Lu Papers or Paper Towels.
*202 6607, Candles, Statues or Pizza Boxes.
*202 6608, Cups, Blankets and Others.
*202 6609, Food Shoppibg like Cola Bottles, Sour Cream and Onion Chips or Cans.
*202 6610, Towels, Cloths, Soap or Containers.
*202 6611, Nachos, Apple N Raspberry Codrial or Stationary.
*202 6612, Basket, Electric Bed with Instructions or Paint.
*202 6613, Aerobar, Birthday Cake or Packet of Candles.
*202 6614, Plates, Blankets or even Vacuum Cleaner.
*202 6615, Towels, Cloths or Dressing Gowns.
*202 6616, Smiths Chips, Heater Vents, Stuff for Lasagna or Cloths.
*202 6617, Pans, Table Spoons or Lids.
*202 6618, Food Shopping like Cans of Coca Cola, Waters, Milk and Others.
*202 6619, Chocolate Milk, Cups of Tea or Extra Mints.
*202 6620, Kitkats, Pens or Domino's Pizza.
*202 6621, Blankets and Pillows or Vacuum Cleaner.
*202 6622, Tea Towels, Cans of Coca Cola or Carlton Draught.
*202 6623, Food Shopping like Bottles of Cola, Waters or New Pyjamas.
*202 6624, Staples, Socks, Hats and Others.
*202 6625, Kitchen Bowls, Pans and Others.
*202 6626, Food Shopping like Colas, Milk or Rainbow Paddlepop.
*202 6627, Tablemats, Sunglasses or Garden Plant.
*202 6628, Boots, Sleep Medicine or Pillow.
*202 6629, Sewing Machine, Tobacco Stuff or Pan.
*202 6630, Food Shopping like Cans of Cocacola, Bottles, Kitkat or M&Ms.
*202 6701, BBQ Chips, Biskits or Grated Cheese.
*202 6702, Lighters, Plates or Cloths.
*202 6703, Hot Dogs, Cola Cans or Lasagna.
*202 6704, Mop, Battery Packs or Doorhandle.
*202 6705, Video Cameras, Internet or McDonalds Bag?.
*202 6706, Pans, Freshmint, or Hotdog Roll.
*202 6707, Food Shopping like Cans of Coca Cola, Cola Bottles, Waters, Shopping Bag or Grated Cheese.
*202 6708, Ktimes, Nutrigrain or Mueslibars.
*202 6709, Saladas, Socks, Vegemite or Textures.
*202 6710, Baskets, Favourites or Cordial Jug.
*202 6711, Shoes like Novo, Vacuum or Carlton Draught.
*202 6712, Aldi Stuff like Mints, Airfryer or Towel.
*202 6713, Food Shopping like Cola Bottles, Cheese, Milk or Paddle Pops.
*202 6714, Baskets, Mask Fresheners or Coat.
*202 6715, Towels, Cloths or Lasagna?.
*202 6716, Soaps, Toothpastes, Cotton Buds and Others.
*202 6717, Cans of Coca Cola, Bottles, Waters, Novo Shoes and Others.
*202 6718, Food Shopping like Upngo, Breads or Cans of Coca Cola.
*202 6719, Quichebox, Plate or Cup or Cheese Machine.
*202 6720, Cups, Milkshakes, Jug or Can of Coca Cola?.
*202 6721, Baskets, Coathangers, Chocolate Milk or Frypan?.
*202 6722, Food Shopping like Cola Bottles, Waters, Milk or Nachos?
*202 6723, Slippers, Blanket Sheets, Clothes Pair and Others.
*202 6724, Pans, Plates, Scissors or Tools.
*202 6725, Aldi Stuff, Domino's Pizza or Lynxspray.
*202 6726, Towels, Lighter or Journal Books.
*202 6727, Food Shopping like Bottles of Cola or Water, Cans or Milk.
*202 6728, Baskets, Battery Packs or Vaporizer and Others.
*202 6729, Sleep Medicines, Deep Heat or Pillows.
*202 6730, Schnitzels, Nesquiks, Milos and Others.
*202 6731, Toothpicks and Nuts and Others.
*202 6801, Food Shopping like Bottles, Cans, Waters and Others.
*202 6802, Plates, Bowls or Battery Packs.
*202 6803, Towels, Blankets, Purse or Boots.
*202 6804, M&M's, Baskets, Cloths or Coathangers.
*202 6805, Boots, Leaves, Texture and Others.
*202 6806, Food Shopping like Cans of Coca Cola, Nachos, Cheese or Milk.
*202 6807, Dressing Gowns, Glasses or Pillows.
*202 6808, Grater Cheese, Pizza, Mat or Plate.
*202 6809, Stylus, Mask, Soaps and Others.
*202 6810, Paper Towels, Staples, Lighter and Others.
*202 6811, Baskets, Cans of Coca Cola or Biskit Shapes.
*202 6812, Blackngold Cola, Blankets or Chocolatebox.
*202 6813, Smiths Chips, Cheese Mozarella or Bread.
*202 6814, Textures, Pens or Basket and Others.
*202 6815, Smoothies, Toys, Chopping Board or Box.
*202 6816, Cups like Gold, Cup of Tea, Metal Bottle and Others.
*202 6817, Food Shopping like Water Bottles, Cans of Coca Cola, Cola Bottles or Chocolate Milk.
*202 6818, Baskets, Keys or Cordial Jug and Others.
*202 6819, Aldi Stuff, Pizza or Pumpsoap.
*202 6820, Towels, Blankets Sheets and Others.
*202 6821, Cheese, Breads, Waters or Cans of Coca Cola and Others.
*202 6822, Sleep Medicone, Quichebox, Towels and Others.
*202 6823, Shoes, Hats or Ashtray and Others.
*202 6824, Cups, Milk, Towels or some Aldi and Others.
*202 6825, Battery Pack, Clothes and Others.
Current, 202 6826. ($#!+).
*202 6827. (Fandom All Wikis, Closed or New).
''2026828''
0guku0qtz3nxvp2p5ggmdhbklac6sjy
762123
762122
2026-09-17T22:51:22Z
~2026-49929-60
75678
762123
wikitext
text/x-wiki
= Test =
917 - Safari
Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control and until the 24 Restriction until no edits made all day, Most Edits made on 6/23, No New Episodes Released on 6/24, Use Account Sometimes.
2:6 — 8:27, 203 days, (8:28+ to fill out).
*8:28, 8:29, 8:30, 8:31, 9:1, (?)
*9:2, 9:3, 9:4, 9:5, 9:6, (?)
*9:7, 9:8 (?)
*9:9 (?)
*9:10 (?)
*9:11 (?)
*9:12 (?)
*9:13 (?)
*9:14 (9:15)
''9:16''
*202 6525, Pot with Fork and Spoon, Bags with Sunglasses.
*202 6526, Baskets, Tobacco Stuff or Socks.
*202 6527, Food Shopping like Cola Bottles, Cans, Cordial and Others.
*202 6528, Socks, Pairs of Shoes, Dressing Gowns.
*202 6529, Towels, Cubes with Things.
*202 6530, Cloths, Flowers Frisun or Soap.
*202 6531, Food Shopping like Party Pies, Waters and Others.
*202 6601, Pairs of Boots, Pillow or Podiatrist.
*202 6602, Plates or Pans, Grated Cheese or Baskets.
*202 6603, Forks, Pans and Other Kitchen Tools.
*202 6604, Cups, Cordial Jug or Strawberry Milk.
*202 6605, Food Shopping like Cans of Coca Cola, Waters, Cordials or Pile of Sauce.
*202 6606, Purses, Lu Papers or Paper Towels.
*202 6607, Candles, Statues or Pizza Boxes.
*202 6608, Cups, Blankets and Others.
*202 6609, Food Shoppibg like Cola Bottles, Sour Cream and Onion Chips or Cans.
*202 6610, Towels, Cloths, Soap or Containers.
*202 6611, Nachos, Apple N Raspberry Codrial or Stationary.
*202 6612, Basket, Electric Bed with Instructions or Paint.
*202 6613, Aerobar, Birthday Cake or Packet of Candles.
*202 6614, Plates, Blankets or even Vacuum Cleaner.
*202 6615, Towels, Cloths or Dressing Gowns.
*202 6616, Smiths Chips, Heater Vents, Stuff for Lasagna or Cloths.
*202 6617, Pans, Table Spoons or Lids.
*202 6618, Food Shopping like Cans of Coca Cola, Waters, Milk and Others.
*202 6619, Chocolate Milk, Cups of Tea or Extra Mints.
*202 6620, Kitkats, Pens or Domino's Pizza.
*202 6621, Blankets and Pillows or Vacuum Cleaner.
*202 6622, Tea Towels, Cans of Coca Cola or Carlton Draught.
*202 6623, Food Shopping like Bottles of Cola, Waters or New Pyjamas.
*202 6624, Staples, Socks, Hats and Others.
*202 6625, Kitchen Bowls, Pans and Others.
*202 6626, Food Shopping like Colas, Milk or Rainbow Paddlepop.
*202 6627, Tablemats, Sunglasses or Garden Plant.
*202 6628, Boots, Sleep Medicine or Pillow.
*202 6629, Sewing Machine, Tobacco Stuff or Pan.
*202 6630, Food Shopping like Cans of Cocacola, Bottles, Kitkat or M&Ms.
*202 6701, BBQ Chips, Biskits or Grated Cheese.
*202 6702, Lighters, Plates or Cloths.
*202 6703, Hot Dogs, Cola Cans or Lasagna.
*202 6704, Mop, Battery Packs or Doorhandle.
*202 6705, Video Cameras, Internet or McDonalds Bag?.
*202 6706, Pans, Freshmint, or Hotdog Roll.
*202 6707, Food Shopping like Cans of Coca Cola, Cola Bottles, Waters, Shopping Bag or Grated Cheese.
*202 6708, Ktimes, Nutrigrain or Mueslibars.
*202 6709, Saladas, Socks, Vegemite or Textures.
*202 6710, Baskets, Favourites or Cordial Jug.
*202 6711, Shoes like Novo, Vacuum or Carlton Draught.
*202 6712, Aldi Stuff like Mints, Airfryer or Towel.
*202 6713, Food Shopping like Cola Bottles, Cheese, Milk or Paddle Pops.
*202 6714, Baskets, Mask Fresheners or Coat.
*202 6715, Towels, Cloths or Lasagna?.
*202 6716, Soaps, Toothpastes, Cotton Buds and Others.
*202 6717, Cans of Coca Cola, Bottles, Waters, Novo Shoes and Others.
*202 6718, Food Shopping like Upngo, Breads or Cans of Coca Cola.
*202 6719, Quichebox, Plate or Cup or Cheese Machine.
*202 6720, Cups, Milkshakes, Jug or Can of Coca Cola?.
*202 6721, Baskets, Coathangers, Chocolate Milk or Frypan?.
*202 6722, Food Shopping like Cola Bottles, Waters, Milk or Nachos?
*202 6723, Slippers, Blanket Sheets, Clothes Pair and Others.
*202 6724, Pans, Plates, Scissors or Tools.
*202 6725, Aldi Stuff, Domino's Pizza or Lynxspray.
*202 6726, Towels, Lighter or Journal Books.
*202 6727, Food Shopping like Bottles of Cola or Water, Cans or Milk.
*202 6728, Baskets, Battery Packs or Vaporizer and Others.
*202 6729, Sleep Medicines, Deep Heat or Pillows.
*202 6730, Schnitzels, Nesquiks, Milos and Others.
*202 6731, Toothpicks and Nuts and Others.
*202 6801, Food Shopping like Bottles, Cans, Waters and Others.
*202 6802, Plates, Bowls or Battery Packs.
*202 6803, Towels, Blankets, Purse or Boots.
*202 6804, M&M's, Baskets, Cloths or Coathangers.
*202 6805, Boots, Leaves, Texture and Others.
*202 6806, Food Shopping like Cans of Coca Cola, Nachos, Cheese or Milk.
*202 6807, Dressing Gowns, Glasses or Pillows.
*202 6808, Grater Cheese, Pizza, Mat or Plate.
*202 6809, Stylus, Mask, Soaps and Others.
*202 6810, Paper Towels, Staples, Lighter and Others.
*202 6811, Baskets, Cans of Coca Cola or Biskit Shapes.
*202 6812, Blackngold Cola, Blankets or Chocolatebox.
*202 6813, Smiths Chips, Cheese Mozarella or Bread.
*202 6814, Textures, Pens or Basket and Others.
*202 6815, Smoothies, Toys, Chopping Board or Box.
*202 6816, Cups like Gold, Cup of Tea, Metal Bottle and Others.
*202 6817, Food Shopping like Water Bottles, Cans of Coca Cola, Cola Bottles or Chocolate Milk.
*202 6818, Baskets, Keys or Cordial Jug and Others.
*202 6819, Aldi Stuff, Pizza or Pumpsoap.
*202 6820, Towels, Blankets Sheets and Others.
*202 6821, Cheese, Breads, Waters or Cans of Coca Cola and Others.
*202 6822, Sleep Medicone, Quichebox, Towels and Others.
*202 6823, Shoes, Hats or Ashtray and Others.
*202 6824, Cups, Milk, Towels or some Aldi and Others.
*202 6825, Battery Pack, Clothes and Others.
Current, 202 6826. ($#!+).
*202 6827. (Fandom All Wikis, Closed or New).
''2026828''
shk7nd121v14xv80gtkdiq7v9a8xxtw
762124
762123
2026-09-17T22:51:45Z
~2026-49929-60
75678
762124
wikitext
text/x-wiki
= Test =
917 - Browser
Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control and until the 24 Restriction until no edits made all day, Most Edits made on 6/23, No New Episodes Released on 6/24, Use Account Sometimes.
2:6 — 8:27, 203 days, (8:28+ to fill out).
*8:28, 8:29, 8:30, 8:31, 9:1, (?)
*9:2, 9:3, 9:4, 9:5, 9:6, (?)
*9:7, 9:8 (?)
*9:9 (?)
*9:10 (?)
*9:11 (?)
*9:12 (?)
*9:13 (?)
*9:14 (9:15)
''9:16''
*202 6525, Pot with Fork and Spoon, Bags with Sunglasses.
*202 6526, Baskets, Tobacco Stuff or Socks.
*202 6527, Food Shopping like Cola Bottles, Cans, Cordial and Others.
*202 6528, Socks, Pairs of Shoes, Dressing Gowns.
*202 6529, Towels, Cubes with Things.
*202 6530, Cloths, Flowers Frisun or Soap.
*202 6531, Food Shopping like Party Pies, Waters and Others.
*202 6601, Pairs of Boots, Pillow or Podiatrist.
*202 6602, Plates or Pans, Grated Cheese or Baskets.
*202 6603, Forks, Pans and Other Kitchen Tools.
*202 6604, Cups, Cordial Jug or Strawberry Milk.
*202 6605, Food Shopping like Cans of Coca Cola, Waters, Cordials or Pile of Sauce.
*202 6606, Purses, Lu Papers or Paper Towels.
*202 6607, Candles, Statues or Pizza Boxes.
*202 6608, Cups, Blankets and Others.
*202 6609, Food Shoppibg like Cola Bottles, Sour Cream and Onion Chips or Cans.
*202 6610, Towels, Cloths, Soap or Containers.
*202 6611, Nachos, Apple N Raspberry Codrial or Stationary.
*202 6612, Basket, Electric Bed with Instructions or Paint.
*202 6613, Aerobar, Birthday Cake or Packet of Candles.
*202 6614, Plates, Blankets or even Vacuum Cleaner.
*202 6615, Towels, Cloths or Dressing Gowns.
*202 6616, Smiths Chips, Heater Vents, Stuff for Lasagna or Cloths.
*202 6617, Pans, Table Spoons or Lids.
*202 6618, Food Shopping like Cans of Coca Cola, Waters, Milk and Others.
*202 6619, Chocolate Milk, Cups of Tea or Extra Mints.
*202 6620, Kitkats, Pens or Domino's Pizza.
*202 6621, Blankets and Pillows or Vacuum Cleaner.
*202 6622, Tea Towels, Cans of Coca Cola or Carlton Draught.
*202 6623, Food Shopping like Bottles of Cola, Waters or New Pyjamas.
*202 6624, Staples, Socks, Hats and Others.
*202 6625, Kitchen Bowls, Pans and Others.
*202 6626, Food Shopping like Colas, Milk or Rainbow Paddlepop.
*202 6627, Tablemats, Sunglasses or Garden Plant.
*202 6628, Boots, Sleep Medicine or Pillow.
*202 6629, Sewing Machine, Tobacco Stuff or Pan.
*202 6630, Food Shopping like Cans of Cocacola, Bottles, Kitkat or M&Ms.
*202 6701, BBQ Chips, Biskits or Grated Cheese.
*202 6702, Lighters, Plates or Cloths.
*202 6703, Hot Dogs, Cola Cans or Lasagna.
*202 6704, Mop, Battery Packs or Doorhandle.
*202 6705, Video Cameras, Internet or McDonalds Bag?.
*202 6706, Pans, Freshmint, or Hotdog Roll.
*202 6707, Food Shopping like Cans of Coca Cola, Cola Bottles, Waters, Shopping Bag or Grated Cheese.
*202 6708, Ktimes, Nutrigrain or Mueslibars.
*202 6709, Saladas, Socks, Vegemite or Textures.
*202 6710, Baskets, Favourites or Cordial Jug.
*202 6711, Shoes like Novo, Vacuum or Carlton Draught.
*202 6712, Aldi Stuff like Mints, Airfryer or Towel.
*202 6713, Food Shopping like Cola Bottles, Cheese, Milk or Paddle Pops.
*202 6714, Baskets, Mask Fresheners or Coat.
*202 6715, Towels, Cloths or Lasagna?.
*202 6716, Soaps, Toothpastes, Cotton Buds and Others.
*202 6717, Cans of Coca Cola, Bottles, Waters, Novo Shoes and Others.
*202 6718, Food Shopping like Upngo, Breads or Cans of Coca Cola.
*202 6719, Quichebox, Plate or Cup or Cheese Machine.
*202 6720, Cups, Milkshakes, Jug or Can of Coca Cola?.
*202 6721, Baskets, Coathangers, Chocolate Milk or Frypan?.
*202 6722, Food Shopping like Cola Bottles, Waters, Milk or Nachos?
*202 6723, Slippers, Blanket Sheets, Clothes Pair and Others.
*202 6724, Pans, Plates, Scissors or Tools.
*202 6725, Aldi Stuff, Domino's Pizza or Lynxspray.
*202 6726, Towels, Lighter or Journal Books.
*202 6727, Food Shopping like Bottles of Cola or Water, Cans or Milk.
*202 6728, Baskets, Battery Packs or Vaporizer and Others.
*202 6729, Sleep Medicines, Deep Heat or Pillows.
*202 6730, Schnitzels, Nesquiks, Milos and Others.
*202 6731, Toothpicks and Nuts and Others.
*202 6801, Food Shopping like Bottles, Cans, Waters and Others.
*202 6802, Plates, Bowls or Battery Packs.
*202 6803, Towels, Blankets, Purse or Boots.
*202 6804, M&M's, Baskets, Cloths or Coathangers.
*202 6805, Boots, Leaves, Texture and Others.
*202 6806, Food Shopping like Cans of Coca Cola, Nachos, Cheese or Milk.
*202 6807, Dressing Gowns, Glasses or Pillows.
*202 6808, Grater Cheese, Pizza, Mat or Plate.
*202 6809, Stylus, Mask, Soaps and Others.
*202 6810, Paper Towels, Staples, Lighter and Others.
*202 6811, Baskets, Cans of Coca Cola or Biskit Shapes.
*202 6812, Blackngold Cola, Blankets or Chocolatebox.
*202 6813, Smiths Chips, Cheese Mozarella or Bread.
*202 6814, Textures, Pens or Basket and Others.
*202 6815, Smoothies, Toys, Chopping Board or Box.
*202 6816, Cups like Gold, Cup of Tea, Metal Bottle and Others.
*202 6817, Food Shopping like Water Bottles, Cans of Coca Cola, Cola Bottles or Chocolate Milk.
*202 6818, Baskets, Keys or Cordial Jug and Others.
*202 6819, Aldi Stuff, Pizza or Pumpsoap.
*202 6820, Towels, Blankets Sheets and Others.
*202 6821, Cheese, Breads, Waters or Cans of Coca Cola and Others.
*202 6822, Sleep Medicone, Quichebox, Towels and Others.
*202 6823, Shoes, Hats or Ashtray and Others.
*202 6824, Cups, Milk, Towels or some Aldi and Others.
*202 6825, Battery Pack, Clothes and Others.
Current, 202 6826. ($#!+).
*202 6827. (Fandom All Wikis, Closed or New).
''2026828''
l9nzyhnx54w68qqfpspyam06os62jkn
762125
762124
2026-09-17T22:52:02Z
~2026-49929-60
75678
762125
wikitext
text/x-wiki
= Test =
917 - Google or Browser
Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control and until the 24 Restriction until no edits made all day, Most Edits made on 6/23, No New Episodes Released on 6/24, Use Account Sometimes.
2:6 — 8:27, 203 days, (8:28+ to fill out).
*8:28, 8:29, 8:30, 8:31, 9:1, (?)
*9:2, 9:3, 9:4, 9:5, 9:6, (?)
*9:7, 9:8 (?)
*9:9 (?)
*9:10 (?)
*9:11 (?)
*9:12 (?)
*9:13 (?)
*9:14 (9:15)
''9:16''
*202 6525, Pot with Fork and Spoon, Bags with Sunglasses.
*202 6526, Baskets, Tobacco Stuff or Socks.
*202 6527, Food Shopping like Cola Bottles, Cans, Cordial and Others.
*202 6528, Socks, Pairs of Shoes, Dressing Gowns.
*202 6529, Towels, Cubes with Things.
*202 6530, Cloths, Flowers Frisun or Soap.
*202 6531, Food Shopping like Party Pies, Waters and Others.
*202 6601, Pairs of Boots, Pillow or Podiatrist.
*202 6602, Plates or Pans, Grated Cheese or Baskets.
*202 6603, Forks, Pans and Other Kitchen Tools.
*202 6604, Cups, Cordial Jug or Strawberry Milk.
*202 6605, Food Shopping like Cans of Coca Cola, Waters, Cordials or Pile of Sauce.
*202 6606, Purses, Lu Papers or Paper Towels.
*202 6607, Candles, Statues or Pizza Boxes.
*202 6608, Cups, Blankets and Others.
*202 6609, Food Shoppibg like Cola Bottles, Sour Cream and Onion Chips or Cans.
*202 6610, Towels, Cloths, Soap or Containers.
*202 6611, Nachos, Apple N Raspberry Codrial or Stationary.
*202 6612, Basket, Electric Bed with Instructions or Paint.
*202 6613, Aerobar, Birthday Cake or Packet of Candles.
*202 6614, Plates, Blankets or even Vacuum Cleaner.
*202 6615, Towels, Cloths or Dressing Gowns.
*202 6616, Smiths Chips, Heater Vents, Stuff for Lasagna or Cloths.
*202 6617, Pans, Table Spoons or Lids.
*202 6618, Food Shopping like Cans of Coca Cola, Waters, Milk and Others.
*202 6619, Chocolate Milk, Cups of Tea or Extra Mints.
*202 6620, Kitkats, Pens or Domino's Pizza.
*202 6621, Blankets and Pillows or Vacuum Cleaner.
*202 6622, Tea Towels, Cans of Coca Cola or Carlton Draught.
*202 6623, Food Shopping like Bottles of Cola, Waters or New Pyjamas.
*202 6624, Staples, Socks, Hats and Others.
*202 6625, Kitchen Bowls, Pans and Others.
*202 6626, Food Shopping like Colas, Milk or Rainbow Paddlepop.
*202 6627, Tablemats, Sunglasses or Garden Plant.
*202 6628, Boots, Sleep Medicine or Pillow.
*202 6629, Sewing Machine, Tobacco Stuff or Pan.
*202 6630, Food Shopping like Cans of Cocacola, Bottles, Kitkat or M&Ms.
*202 6701, BBQ Chips, Biskits or Grated Cheese.
*202 6702, Lighters, Plates or Cloths.
*202 6703, Hot Dogs, Cola Cans or Lasagna.
*202 6704, Mop, Battery Packs or Doorhandle.
*202 6705, Video Cameras, Internet or McDonalds Bag?.
*202 6706, Pans, Freshmint, or Hotdog Roll.
*202 6707, Food Shopping like Cans of Coca Cola, Cola Bottles, Waters, Shopping Bag or Grated Cheese.
*202 6708, Ktimes, Nutrigrain or Mueslibars.
*202 6709, Saladas, Socks, Vegemite or Textures.
*202 6710, Baskets, Favourites or Cordial Jug.
*202 6711, Shoes like Novo, Vacuum or Carlton Draught.
*202 6712, Aldi Stuff like Mints, Airfryer or Towel.
*202 6713, Food Shopping like Cola Bottles, Cheese, Milk or Paddle Pops.
*202 6714, Baskets, Mask Fresheners or Coat.
*202 6715, Towels, Cloths or Lasagna?.
*202 6716, Soaps, Toothpastes, Cotton Buds and Others.
*202 6717, Cans of Coca Cola, Bottles, Waters, Novo Shoes and Others.
*202 6718, Food Shopping like Upngo, Breads or Cans of Coca Cola.
*202 6719, Quichebox, Plate or Cup or Cheese Machine.
*202 6720, Cups, Milkshakes, Jug or Can of Coca Cola?.
*202 6721, Baskets, Coathangers, Chocolate Milk or Frypan?.
*202 6722, Food Shopping like Cola Bottles, Waters, Milk or Nachos?
*202 6723, Slippers, Blanket Sheets, Clothes Pair and Others.
*202 6724, Pans, Plates, Scissors or Tools.
*202 6725, Aldi Stuff, Domino's Pizza or Lynxspray.
*202 6726, Towels, Lighter or Journal Books.
*202 6727, Food Shopping like Bottles of Cola or Water, Cans or Milk.
*202 6728, Baskets, Battery Packs or Vaporizer and Others.
*202 6729, Sleep Medicines, Deep Heat or Pillows.
*202 6730, Schnitzels, Nesquiks, Milos and Others.
*202 6731, Toothpicks and Nuts and Others.
*202 6801, Food Shopping like Bottles, Cans, Waters and Others.
*202 6802, Plates, Bowls or Battery Packs.
*202 6803, Towels, Blankets, Purse or Boots.
*202 6804, M&M's, Baskets, Cloths or Coathangers.
*202 6805, Boots, Leaves, Texture and Others.
*202 6806, Food Shopping like Cans of Coca Cola, Nachos, Cheese or Milk.
*202 6807, Dressing Gowns, Glasses or Pillows.
*202 6808, Grater Cheese, Pizza, Mat or Plate.
*202 6809, Stylus, Mask, Soaps and Others.
*202 6810, Paper Towels, Staples, Lighter and Others.
*202 6811, Baskets, Cans of Coca Cola or Biskit Shapes.
*202 6812, Blackngold Cola, Blankets or Chocolatebox.
*202 6813, Smiths Chips, Cheese Mozarella or Bread.
*202 6814, Textures, Pens or Basket and Others.
*202 6815, Smoothies, Toys, Chopping Board or Box.
*202 6816, Cups like Gold, Cup of Tea, Metal Bottle and Others.
*202 6817, Food Shopping like Water Bottles, Cans of Coca Cola, Cola Bottles or Chocolate Milk.
*202 6818, Baskets, Keys or Cordial Jug and Others.
*202 6819, Aldi Stuff, Pizza or Pumpsoap.
*202 6820, Towels, Blankets Sheets and Others.
*202 6821, Cheese, Breads, Waters or Cans of Coca Cola and Others.
*202 6822, Sleep Medicone, Quichebox, Towels and Others.
*202 6823, Shoes, Hats or Ashtray and Others.
*202 6824, Cups, Milk, Towels or some Aldi and Others.
*202 6825, Battery Pack, Clothes and Others.
Current, 202 6826. ($#!+).
*202 6827. (Fandom All Wikis, Closed or New).
''2026828''
4tki56sk5jzltsm310ko39fqj0acdzj
762126
762125
2026-09-17T22:52:32Z
~2026-49929-60
75678
762126
wikitext
text/x-wiki
= Test =
917 - Google or Browsers
Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control and until the 24 Restriction until no edits made all day, Most Edits made on 6/23, No New Episodes Released on 6/24, Use Account Sometimes.
2:6 — 8:27, 203 days, (8:28+ to fill out).
*8:28, 8:29, 8:30, 8:31, 9:1, (?)
*9:2, 9:3, 9:4, 9:5, 9:6, (?)
*9:7, 9:8 (?)
*9:9 (?)
*9:10 (?)
*9:11 (?)
*9:12 (?)
*9:13 (?)
*9:14 (9:15)
''9:16''
*202 6525, Pot with Fork and Spoon, Bags with Sunglasses.
*202 6526, Baskets, Tobacco Stuff or Socks.
*202 6527, Food Shopping like Cola Bottles, Cans, Cordial and Others.
*202 6528, Socks, Pairs of Shoes, Dressing Gowns.
*202 6529, Towels, Cubes with Things.
*202 6530, Cloths, Flowers Frisun or Soap.
*202 6531, Food Shopping like Party Pies, Waters and Others.
*202 6601, Pairs of Boots, Pillow or Podiatrist.
*202 6602, Plates or Pans, Grated Cheese or Baskets.
*202 6603, Forks, Pans and Other Kitchen Tools.
*202 6604, Cups, Cordial Jug or Strawberry Milk.
*202 6605, Food Shopping like Cans of Coca Cola, Waters, Cordials or Pile of Sauce.
*202 6606, Purses, Lu Papers or Paper Towels.
*202 6607, Candles, Statues or Pizza Boxes.
*202 6608, Cups, Blankets and Others.
*202 6609, Food Shoppibg like Cola Bottles, Sour Cream and Onion Chips or Cans.
*202 6610, Towels, Cloths, Soap or Containers.
*202 6611, Nachos, Apple N Raspberry Codrial or Stationary.
*202 6612, Basket, Electric Bed with Instructions or Paint.
*202 6613, Aerobar, Birthday Cake or Packet of Candles.
*202 6614, Plates, Blankets or even Vacuum Cleaner.
*202 6615, Towels, Cloths or Dressing Gowns.
*202 6616, Smiths Chips, Heater Vents, Stuff for Lasagna or Cloths.
*202 6617, Pans, Table Spoons or Lids.
*202 6618, Food Shopping like Cans of Coca Cola, Waters, Milk and Others.
*202 6619, Chocolate Milk, Cups of Tea or Extra Mints.
*202 6620, Kitkats, Pens or Domino's Pizza.
*202 6621, Blankets and Pillows or Vacuum Cleaner.
*202 6622, Tea Towels, Cans of Coca Cola or Carlton Draught.
*202 6623, Food Shopping like Bottles of Cola, Waters or New Pyjamas.
*202 6624, Staples, Socks, Hats and Others.
*202 6625, Kitchen Bowls, Pans and Others.
*202 6626, Food Shopping like Colas, Milk or Rainbow Paddlepop.
*202 6627, Tablemats, Sunglasses or Garden Plant.
*202 6628, Boots, Sleep Medicine or Pillow.
*202 6629, Sewing Machine, Tobacco Stuff or Pan.
*202 6630, Food Shopping like Cans of Cocacola, Bottles, Kitkat or M&Ms.
*202 6701, BBQ Chips, Biskits or Grated Cheese.
*202 6702, Lighters, Plates or Cloths.
*202 6703, Hot Dogs, Cola Cans or Lasagna.
*202 6704, Mop, Battery Packs or Doorhandle.
*202 6705, Video Cameras, Internet or McDonalds Bag?.
*202 6706, Pans, Freshmint, or Hotdog Roll.
*202 6707, Food Shopping like Cans of Coca Cola, Cola Bottles, Waters, Shopping Bag or Grated Cheese.
*202 6708, Ktimes, Nutrigrain or Mueslibars.
*202 6709, Saladas, Socks, Vegemite or Textures.
*202 6710, Baskets, Favourites or Cordial Jug.
*202 6711, Shoes like Novo, Vacuum or Carlton Draught.
*202 6712, Aldi Stuff like Mints, Airfryer or Towel.
*202 6713, Food Shopping like Cola Bottles, Cheese, Milk or Paddle Pops.
*202 6714, Baskets, Mask Fresheners or Coat.
*202 6715, Towels, Cloths or Lasagna?.
*202 6716, Soaps, Toothpastes, Cotton Buds and Others.
*202 6717, Cans of Coca Cola, Bottles, Waters, Novo Shoes and Others.
*202 6718, Food Shopping like Upngo, Breads or Cans of Coca Cola.
*202 6719, Quichebox, Plate or Cup or Cheese Machine.
*202 6720, Cups, Milkshakes, Jug or Can of Coca Cola?.
*202 6721, Baskets, Coathangers, Chocolate Milk or Frypan?.
*202 6722, Food Shopping like Cola Bottles, Waters, Milk or Nachos?
*202 6723, Slippers, Blanket Sheets, Clothes Pair and Others.
*202 6724, Pans, Plates, Scissors or Tools.
*202 6725, Aldi Stuff, Domino's Pizza or Lynxspray.
*202 6726, Towels, Lighter or Journal Books.
*202 6727, Food Shopping like Bottles of Cola or Water, Cans or Milk.
*202 6728, Baskets, Battery Packs or Vaporizer and Others.
*202 6729, Sleep Medicines, Deep Heat or Pillows.
*202 6730, Schnitzels, Nesquiks, Milos and Others.
*202 6731, Toothpicks and Nuts and Others.
*202 6801, Food Shopping like Bottles, Cans, Waters and Others.
*202 6802, Plates, Bowls or Battery Packs.
*202 6803, Towels, Blankets, Purse or Boots.
*202 6804, M&M's, Baskets, Cloths or Coathangers.
*202 6805, Boots, Leaves, Texture and Others.
*202 6806, Food Shopping like Cans of Coca Cola, Nachos, Cheese or Milk.
*202 6807, Dressing Gowns, Glasses or Pillows.
*202 6808, Grater Cheese, Pizza, Mat or Plate.
*202 6809, Stylus, Mask, Soaps and Others.
*202 6810, Paper Towels, Staples, Lighter and Others.
*202 6811, Baskets, Cans of Coca Cola or Biskit Shapes.
*202 6812, Blackngold Cola, Blankets or Chocolatebox.
*202 6813, Smiths Chips, Cheese Mozarella or Bread.
*202 6814, Textures, Pens or Basket and Others.
*202 6815, Smoothies, Toys, Chopping Board or Box.
*202 6816, Cups like Gold, Cup of Tea, Metal Bottle and Others.
*202 6817, Food Shopping like Water Bottles, Cans of Coca Cola, Cola Bottles or Chocolate Milk.
*202 6818, Baskets, Keys or Cordial Jug and Others.
*202 6819, Aldi Stuff, Pizza or Pumpsoap.
*202 6820, Towels, Blankets Sheets and Others.
*202 6821, Cheese, Breads, Waters or Cans of Coca Cola and Others.
*202 6822, Sleep Medicone, Quichebox, Towels and Others.
*202 6823, Shoes, Hats or Ashtray and Others.
*202 6824, Cups, Milk, Towels or some Aldi and Others.
*202 6825, Battery Pack, Clothes and Others.
Current, 202 6826. ($#!+).
*202 6827. (Fandom All Wikis, Closed or New).
''2026828''
0ltcmhkn4mut7ugk654164yb3xncuws
762127
762126
2026-09-17T22:52:59Z
~2026-49929-60
75678
/* Test */ All dobe
762127
wikitext
text/x-wiki
= Test =
917 - Google or Browsers
Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control and until the 24 Restriction until no edits made all day, Most Edits made on 6/23, No New Episodes Released on 6/24, Use Account Sometimes.
2:6 — 8:27, 203 days, (8:28+ to fill out).
*8:28, 8:29, 8:30, 8:31, 9:1, (?)
*9:2, 9:3, 9:4, 9:5, 9:6, (?)
*9:7, 9:8 (?)
*9:9 (?)
*9:10 (?)
*9:11 (?)
*9:12 (?)
*9:13 (?)
*9:14 (?)
*9:15 (9:16)
''9:17''
*202 6525, Pot with Fork and Spoon, Bags with Sunglasses.
*202 6526, Baskets, Tobacco Stuff or Socks.
*202 6527, Food Shopping like Cola Bottles, Cans, Cordial and Others.
*202 6528, Socks, Pairs of Shoes, Dressing Gowns.
*202 6529, Towels, Cubes with Things.
*202 6530, Cloths, Flowers Frisun or Soap.
*202 6531, Food Shopping like Party Pies, Waters and Others.
*202 6601, Pairs of Boots, Pillow or Podiatrist.
*202 6602, Plates or Pans, Grated Cheese or Baskets.
*202 6603, Forks, Pans and Other Kitchen Tools.
*202 6604, Cups, Cordial Jug or Strawberry Milk.
*202 6605, Food Shopping like Cans of Coca Cola, Waters, Cordials or Pile of Sauce.
*202 6606, Purses, Lu Papers or Paper Towels.
*202 6607, Candles, Statues or Pizza Boxes.
*202 6608, Cups, Blankets and Others.
*202 6609, Food Shoppibg like Cola Bottles, Sour Cream and Onion Chips or Cans.
*202 6610, Towels, Cloths, Soap or Containers.
*202 6611, Nachos, Apple N Raspberry Codrial or Stationary.
*202 6612, Basket, Electric Bed with Instructions or Paint.
*202 6613, Aerobar, Birthday Cake or Packet of Candles.
*202 6614, Plates, Blankets or even Vacuum Cleaner.
*202 6615, Towels, Cloths or Dressing Gowns.
*202 6616, Smiths Chips, Heater Vents, Stuff for Lasagna or Cloths.
*202 6617, Pans, Table Spoons or Lids.
*202 6618, Food Shopping like Cans of Coca Cola, Waters, Milk and Others.
*202 6619, Chocolate Milk, Cups of Tea or Extra Mints.
*202 6620, Kitkats, Pens or Domino's Pizza.
*202 6621, Blankets and Pillows or Vacuum Cleaner.
*202 6622, Tea Towels, Cans of Coca Cola or Carlton Draught.
*202 6623, Food Shopping like Bottles of Cola, Waters or New Pyjamas.
*202 6624, Staples, Socks, Hats and Others.
*202 6625, Kitchen Bowls, Pans and Others.
*202 6626, Food Shopping like Colas, Milk or Rainbow Paddlepop.
*202 6627, Tablemats, Sunglasses or Garden Plant.
*202 6628, Boots, Sleep Medicine or Pillow.
*202 6629, Sewing Machine, Tobacco Stuff or Pan.
*202 6630, Food Shopping like Cans of Cocacola, Bottles, Kitkat or M&Ms.
*202 6701, BBQ Chips, Biskits or Grated Cheese.
*202 6702, Lighters, Plates or Cloths.
*202 6703, Hot Dogs, Cola Cans or Lasagna.
*202 6704, Mop, Battery Packs or Doorhandle.
*202 6705, Video Cameras, Internet or McDonalds Bag?.
*202 6706, Pans, Freshmint, or Hotdog Roll.
*202 6707, Food Shopping like Cans of Coca Cola, Cola Bottles, Waters, Shopping Bag or Grated Cheese.
*202 6708, Ktimes, Nutrigrain or Mueslibars.
*202 6709, Saladas, Socks, Vegemite or Textures.
*202 6710, Baskets, Favourites or Cordial Jug.
*202 6711, Shoes like Novo, Vacuum or Carlton Draught.
*202 6712, Aldi Stuff like Mints, Airfryer or Towel.
*202 6713, Food Shopping like Cola Bottles, Cheese, Milk or Paddle Pops.
*202 6714, Baskets, Mask Fresheners or Coat.
*202 6715, Towels, Cloths or Lasagna?.
*202 6716, Soaps, Toothpastes, Cotton Buds and Others.
*202 6717, Cans of Coca Cola, Bottles, Waters, Novo Shoes and Others.
*202 6718, Food Shopping like Upngo, Breads or Cans of Coca Cola.
*202 6719, Quichebox, Plate or Cup or Cheese Machine.
*202 6720, Cups, Milkshakes, Jug or Can of Coca Cola?.
*202 6721, Baskets, Coathangers, Chocolate Milk or Frypan?.
*202 6722, Food Shopping like Cola Bottles, Waters, Milk or Nachos?
*202 6723, Slippers, Blanket Sheets, Clothes Pair and Others.
*202 6724, Pans, Plates, Scissors or Tools.
*202 6725, Aldi Stuff, Domino's Pizza or Lynxspray.
*202 6726, Towels, Lighter or Journal Books.
*202 6727, Food Shopping like Bottles of Cola or Water, Cans or Milk.
*202 6728, Baskets, Battery Packs or Vaporizer and Others.
*202 6729, Sleep Medicines, Deep Heat or Pillows.
*202 6730, Schnitzels, Nesquiks, Milos and Others.
*202 6731, Toothpicks and Nuts and Others.
*202 6801, Food Shopping like Bottles, Cans, Waters and Others.
*202 6802, Plates, Bowls or Battery Packs.
*202 6803, Towels, Blankets, Purse or Boots.
*202 6804, M&M's, Baskets, Cloths or Coathangers.
*202 6805, Boots, Leaves, Texture and Others.
*202 6806, Food Shopping like Cans of Coca Cola, Nachos, Cheese or Milk.
*202 6807, Dressing Gowns, Glasses or Pillows.
*202 6808, Grater Cheese, Pizza, Mat or Plate.
*202 6809, Stylus, Mask, Soaps and Others.
*202 6810, Paper Towels, Staples, Lighter and Others.
*202 6811, Baskets, Cans of Coca Cola or Biskit Shapes.
*202 6812, Blackngold Cola, Blankets or Chocolatebox.
*202 6813, Smiths Chips, Cheese Mozarella or Bread.
*202 6814, Textures, Pens or Basket and Others.
*202 6815, Smoothies, Toys, Chopping Board or Box.
*202 6816, Cups like Gold, Cup of Tea, Metal Bottle and Others.
*202 6817, Food Shopping like Water Bottles, Cans of Coca Cola, Cola Bottles or Chocolate Milk.
*202 6818, Baskets, Keys or Cordial Jug and Others.
*202 6819, Aldi Stuff, Pizza or Pumpsoap.
*202 6820, Towels, Blankets Sheets and Others.
*202 6821, Cheese, Breads, Waters or Cans of Coca Cola and Others.
*202 6822, Sleep Medicone, Quichebox, Towels and Others.
*202 6823, Shoes, Hats or Ashtray and Others.
*202 6824, Cups, Milk, Towels or some Aldi and Others.
*202 6825, Battery Pack, Clothes and Others.
Current, 202 6826. ($#!+).
*202 6827. (Fandom All Wikis, Closed or New).
''2026828''
gzkw9humh0i2gi6au08zd52r8ki8evk
Design for the Environment
0
113508
762128
742131
2026-09-18T00:04:31Z
InternetArchiveBot
34092
Rescuing 0 sources and tagging 1 as dead.) #IABot (v2.0.9.5
762128
wikitext
text/x-wiki
'''Design for the Environment''' (DfE) is a design approach to reduce the overall human health and environmental impact of a product, process or service, where impacts are considered across its [[life cycle]]. Different software tools have been developed to assist designers in finding optimized products or processes/services. DfE is also the original name of a [[United States Environmental Protection Agency]] (EPA) program, created in 1992, that works to prevent pollution, and the risk pollution presents to humans and the environment. The program provides information regarding safer [[Chemical substance|chemical formulations]] for cleaning and other products.<ref name=DfE>{{cite web |url=https://www.epa.gov/saferchoice |title=Safer Choice |publisher=U.S. Environmental Protection Agency (EPA) |location=Washington, DC |date=2017-06-21}}</ref> EPA renamed its program [[EPA Safer Choice|"Safer Choice"]] in 2015.<ref name="EPA-history">{{cite web |url=https://www.epa.gov/saferchoice/history-safer-choice-and-design-environment |title=History of Safer Choice and Design for the Environment |date=2017-04-19 |publisher=EPA}}</ref> test123
this is an edit
[http://sdjfkdsjl.com]
af edit
this is a new edit
== Introduction ==
[[File:Updated Fig.1 Pie.png|thumb|Each piece of the pie chart depicts the role that the individual processes play in the overall design and production of a product. In recent years the environment has begun to play an important role in this diagram. If any piece is missing, production may not be able to occur. This figure was adopted from Conrad Luttropp and Jessica Lagerstedt.<ref>{{cite journal|last=Luttropp|first=Conrad|author2=Jessica Lagerstedt|title=EcoDesign and The Ten Golden Rules: generic advice for merging environmental aspects into product development|journal=Journal of Cleaner Production|year=2006}}</ref>]]
Initial guidelines for a DfE approach were written in 1990 by [[East Meets West (non-governmental organization)|East Meets West]], a New York-based non-governmental organization. It became a global movement targeting design initiatives and incorporating environmental motives to improve product design in order to minimize health and environmental impacts by incorporating it from design stage all the way to the manufacturing process. The DfE strategy aims to improve technology and design tactics to expand the scope of products. By incorporating [[eco-efficiency]] into design tactics, DfE takes into consideration the entire life-cycle of the product, while still making products usable but minimizing resource use. The key focus of DfE is to minimize the [[Environmental economics|environmental-economic]] cost to consumers<ref>{{cite journal|last=Luttropp|first=Conrad|author2=Jessica Lagerstedt|title=Design and The Ten Golden Rules: generic advice for merging environmental aspects into product development|journal=Journal of Cleaner Production|date=11 November 2011|volume=14|pages=1396–1408|doi=10.1016/j.jclepro.2005.11.022}}</ref> while still focusing on the life-cycle framework of the product. By balancing both customer needs as well as environmental and social impacts DfE aims to "improve the product use experience both for consumers and producers, while minimally impacting the environment".
==Design for Environment practices==
[[File:Designforenvironment fig1.png|thumb|Resource consumption and mitigation strategies for product production which minimizes environmental and health impacts.This figure has been adapted from Spangenberg et al.:<ref>{{cite journal|last=Spangenberg|first=Joachim H. |author2=Alastair Fuad- Luke |author3=Karen Blincoe|title=Design for Sustainability (DfS): the interface of sustainable production and consumption|journal=Journal of Cleaner Production|date=16 June 2010|volume=18|pages=1485–1493|doi=10.1016/j.jclepro.2010.06.002}}<!--|accessdate=April 10, 2013--></ref>]]
Four main concepts that fall under the DfE umbrella.<ref name="DfE"/>
* ''Design for environmental processing and manufacturing'': Raw material [[Resource extraction|extraction]] (mining, drilling, etc.), processing (processing reusable materials, metal melting, etc.) and [[manufacturing]] are done using materials and processes which are not dangerous to the environment or the employees working on said processes. This includes the minimization of waste and hazardous by-products, [[air pollution]], energy expenditure and other factors.
* ''Design for environmental packaging'': Materials used in [[packaging]] are environmentally responsible, which can be achieved through the reuse of shipping products, elimination of unnecessary paper and packaging products, efficient use of materials and space, use of [[Recycling|recycled]] and/or recyclable materials.
* ''Design for disposal or reuse'': The [[End-of-life (product)|end-of-life]] of a product is very important, because some products emit dangerous chemicals into the air, ground and water after they are disposed of in a landfill. Planning for the [[reuse]] or [[Remanufacturing|refurbishing]] of a product will change the types of materials that would be used, how they could later be disassembled and reused, and the environmental impacts such materials have.
* ''Design for energy efficiency'': The design of products to reduce overall energy consumption throughout the product's life.
[[Life-cycle assessment]] (LCA) is employed to forecast the impacts of different (production) alternatives of the product in question, thus being able to choose the most [[environmentally friendly]]. A life cycle analysis can serve as a tool when determining the environmental impact of a product or process. Proper LCAs can help a designer compare several different products according to several categories, such as [[energy]] use, [[toxicity]], acidification, [[Carbon dioxide|CO2 emissions]], [[ozone depletion]], [[resource depletion]] and many others. By comparing different products, designers can make decisions about which environmental hazard to focus on in order to make the product more environmentally friendly.
==Why do firms want to design for the environment?==
Modern day businesses all aim to produce goods at a low cost while maintaining quality, staying competitive in the global marketplace, and meeting consumer preferences for more environment friendly products. To help businesses meet these challenges, EPA encourages businesses to incorporate environmental considerations into the design process. The benefits of incorporating DfE include: cost savings, reduced business and environmental risks, expanded business and market opportunities, and to meet environmental regulations.<ref name="EPA brochure 2001">{{cite report |date=March 2001 |title=The U.S. Environmental Protection Agency’s Design for the Environment Program |url=https://nepis.epa.gov/Exe/ZyPURL.cgi?Dockey=2000132E.txt |publisher=EPA |id=EPA 744-F-00-020. Brochure.}}</ref>
==Companies and products==
[[File:Designfortheenvironment Fig3.png|thumb|Designfortheenvironment Fig3]]
*[[Starbucks]]: Starbucks is decreasing its carbon footprint by building more energy efficient stores and facilities, conserving energy and water, and purchasing renewable energy credits. Starbucks has achieved [[Leadership in Energy and Environmental Design|LEED]] certificates in 116 stores in 12 countries. Starbucks has even created a portable, LEED certified store in Denver. It is Starbucks' goal to reduce energy consumption by 25% and to cover 100% of its electricity with renewable energy by 2015.<ref>{{cite web|last=Wilson|first=Mark|title=An Experimental New Starbucks Store: Tiny, Portable, and Hyper Local|url=http://www.fastcodesign.com/1670889/an-experimental-new-starbucks-store-tiny-portable-and-hyper-local#1|publisher=Co.design}}</ref>
*[[Hewlett Packard]]: HP is working towards reducing energy used in manufacturing, developing materials that have less environmental impact, and designing easily recyclable equipment.<ref>{{cite web|title=HP Design for Environment|url=http://www.destinationgreenit.com/hp-design-for-environment|publisher=Destination Green IT|accessdate=14 April 2013|url-status=dead|archiveurl=https://web.archive.org/web/20130331090652/http://www.destinationgreenit.com/hp-design-for-environment|archivedate=31 March 2013}}</ref>
*[[IBM]]: Their goal is to extend product life beyond just production, and to use reusable and recyclable products. This means that IBM is currently working on creating products that can be safely disposed of at the end of its product life. They are also reducing consumption of energy to minimize their carbon footprint.<ref>{{cite web|title=Product Stewardship|url=http://www.ibm.com/ibm/environment/products/|publisher=IBM|accessdate=14 April 2013}}</ref>
*[[Philips]]: For almost 20 years now, sustainable development has been a crucial part of Philips decision making and manufacturing process. Philips' goal is to produce products with their environmental responsibility in mind. Not only are they working on reducing energy during the manufacturing process, Phillips is also participating in a unique project, philanthropy through design. Since 2005, Philips has been working on and developing philanthropy through design. They collaborate with other organizations to use their expertise and innovation to help the more fragile parts of our society.<ref>{{cite web|title=Towards a Sustainable Future|url=http://www.design.philips.com/sites/philipsdesign/about/design/aboutus/sustainablefuture/index.page|publisher=Philips}}{{Dead link|date=September 2026 |bot=InternetArchiveBot |fix-attempted=yes }}</ref>
Besides these large brand names there are several other consumer product companies in the DfE program this including:
*Atlantic Chemical & Equipment Co.
*American Cleaning Solutions
*BCD Supply
*Beta Technology
*Brighton USA<ref>{{cite web|title=Labeled Products and Our Partners|url=http://www.epa.gov/dfe/pubs/projects/formulat/formpart.htm|publisher=EPA|accessdate=14 April 2013}}{{Update inline|date=July 2017}}</ref>
==How does a business design for the environment?==
A business can design for the environment by:
* Evaluating the human health and environmental impacts of its processes and products.
* Identifying what information is needed to make human health and environment decisions
* Conducting an assessment of alternatives
* Considering cross-media impacts and the benefits of substituting chemicals
* Reducing the use and release of toxic chemicals through the innovation of cleaner technologies that use safer chemicals.
* Implementing pollution prevention, energy efficiency, and other resource conservation measures.
* Making products that can be reused and recycled
* Monitoring the environmental impacts and costs associated with each product or process
* Recognizing that although change can be rapid, in many cases a cycle of evaluation and continuous improvement is needed.<ref name=DfE />
==Safer Choice labeling program==
EPA's DfE labeling program was renamed [[EPA Safer Choice|"Safer Choice"]] in 2015.<ref name="EPA-history"/>
==Current U.S. laws and regulations encouraging DfE in the electronics industry==
===National Ambient Air Quality Standards (NAAQS)===
EPA promulgated the [[National Ambient Air Quality Standards]] (NAAQS) to establish basic air pollution control requirements across the U.S. The NAAQS sets standards on six main sources of pollutants, which include emissions of: [[ozone]] (0.12 ppm per 1 hour), [[carbon monoxide]] (35 ppm per 1 hour; primary standard), [[particulate matter]] (50g/m^3 at an annual arithmetic mean), [[sulfur dioxide]] (80g/m^3 at an annual arithmetic mean), [[nitrogen dioxide]] (100g/m^3 at an annual arithmetic mean), and [[lead]] emissions (1.5g/m^3 at an annual arithmetic mean).<ref>{{cite web |title=NAAQS Table |url=https://www.epa.gov/criteria-air-pollutants/naaqs-table |website=Criteria Air Pollutants |publisher=EPA |date=2016-12-20}}</ref>
===Stratospheric ozone protection===
[[Stratospheric ozone]] protection is required by section 602 of the [[Clean Air Act (United States)|Clean Air Act]] of 1990. This regulation aims to decrease emission of [[chlorofluorocarbon]]s (CFCs) and other chemicals that are destroying the stratospheric ozone layer. The protection initiative categorizes ozone-depleting substances into two classes: Class I, and Class II.<ref name="Clean Air Act Requirements">{{cite web |title=Ozone Protection under Title VI of the Clean Air Act |url=https://www.epa.gov/ozone-layer-protection/ozone-protection-under-title-vi-clean-air-act |publisher=EPA |date=2016-12-09}}</ref>
Class I substances include 20 different kinds of chemicals and have all been phased-out of production processes since 2000. Class II substances consist of 33 different hydro-chlorofluorocarbons (HCFCs). The EPA has already begun plans to decrease emissions in HCFCs and plan to completely phase out the class II substances by 2030.<ref name="Clean Air Act Requirements"/>
===Reporting requirements for releases of toxic substances===
A firm operating in the electronics industry in [[Standard Industrial Classification]] (SIC) Codes 20-39 that has more than 10 full-time employees and consumes more than 10,000 lbs per year of any toxic chemical lists in 40 CFR 372.65 must file a toxic release inventory.<ref>{{cite web|title=Superfund and Community Right-to-Know Requirements|url=http://www.epa.gov/dfe/pubs/pwb/tech_rep/fedregs/regsectd.htm#D4|publisher=Environmental Protection Agency|accessdate=17 April 2013}}</ref>
===Other regulations===
* [[National Emissions Standards for Hazardous Air Pollutants]] (NESHAP)
* [[Clean Water Act|National Pollutant Discharge Elimination System]] (NPDES–Water pollution permit program)
* [[Safe Drinking Water Act#Underground Injection Control (UIC) Program |Underground Injection Control Program]]
* [[Hazardous waste]] management
* [[Underground storage tank]] management<ref>{{cite report |title=Federal Environmental Regulations Affecting the Electronics Industry |url=https://nepis.epa.gov/Exe/ZyPURL.cgi?Dockey=200012F6.txt |date=September 1995 |publisher=EPA |id=EPA 744-B-95-001}}</ref>
==See also==
{{Div col|colwidth=20em}}
* [[Biodiversity]]
* [[Conservation movement]]
* [[Design impact measures]]
* [[Ecodesign]]
* [[Environmental design]]
* [[Environmental movement]]
* [[Leadership in Energy and Environmental Design]]
* [[Life-cycle assessment]]
* [[Natural environment]]
* [[Sustainable design]]
* [[Sustainability]]
{{Div col end}}
==References==
{{Reflist}}
==External links==
* [http://eplca.jrc.ec.europa.eu/ The European Union: The European Platform on Life Cycle Assessment]
* [https://www.enggstudy.com/design-for-the-environment-methods Sustainable design for the environment]
* [http://www.lbp-gabi.de/30-1-Home.html Department Life Cycle Engineering, University of Stuttgart] (English)
* [https://web.archive.org/web/20101229105757/http://www.sballiance.org/ Sustainable Building Alliance.org]
* [http://www.asla.org/ContentDetail.aspx?id=25156 Sustainable Residential Design.org: Using Low-Impact Materials Resource Guide]
{{Industrial ecology}}
{{DEFAULTSORT:Design For Environment}}
[[Category:Sustainable design]]
[[Category:Design for X]]
[[Category:Industrial ecology]]
[[Category:United States Environmental Protection Agency]]
<noinclude>
<small>This page was moved from [[:en:Design for the Environment]]. Its edit history can be viewed at [[Design for the Environment/edithistory]]</small></noinclude>
6930aqoxf4lwi57hqw7uzr9fdk30ai2
Foo
0
116510
762110
735713
2026-09-17T16:46:51Z
Cooltey
37344
/* */ test
762110
wikitext
text/x-wiki
{{Short description|foo three: fall of the trees}}
Hello, world!
Fu-schnickens
temp
testing
testing123
Temp account edit 3
Temp account on an iPad yay!
have you ever eaten a bagel and just '''died?'''
Test
bar
h6zhhckm9upwwk9d0c8u8sgghm341a5
User:SHB/sandbox
2
119344
762135
476707
2026-09-18T03:46:04Z
Max
57656
Max moved page [[User:SHB2000/sandbox]] to [[User:SHB/sandbox]]: Automatically moved page while renaming the user "[[Special:CentralAuth/SHB2000|SHB2000]]" to "[[Special:CentralAuth/SHB|SHB]]"
476707
wikitext
text/x-wiki
phoiac9h4m842xq45sp7s6u21eteeq1
User talk:SHB
3
120507
762131
480635
2026-09-18T03:46:03Z
Max
57656
Max moved page [[User talk:SHB2000]] to [[User talk:SHB]]: Automatically moved page while renaming the user "[[Special:CentralAuth/SHB2000|SHB2000]]" to "[[Special:CentralAuth/SHB|SHB]]"
480635
wikitext
text/x-wiki
<div style="border: 1rem #dd0000 ridge; padding: 0.5em;">Hello! Please message me on [[m:User talk:SHB2000|meta.wikimedia.org]] instead. I may not notice messages on this page.</div>
<div style="padding: 2em; border: medium solid #4740A8;">
[[File:TUT ninja developer.png|right|220px|link=]]
<span style="color: #539ED8; font-size: 180%;">'''Welcome to [[MediaWiki:The Userscript Tour|<span style="color: #539ED8; ">The Userscript Tour</span>]]!'''</span>
<br />
<br />
'''Hi mate!''' We're so delighted you wanted to play, to unveil the realm of userscripts. Trust us, you are sure to appreciate the power and flexibility of userscripts in no time! The Tour is divided into four missions, each with its own goals to help you implement userscripts with fundamental constructs incrementally.
Together these ''recipes of development'' aid you build cool JavaScript programs to change the very appearance and behaviour of your user account :)
{{:TUT/Navigation1}}
</div>
2e41rvzqa386aqtl2r1bu0nox1d8xxl
User:SHB/common.js
2
120508
762137
476829
2026-09-18T03:47:04Z
Max
57656
Max moved page [[User:SHB2000/common.js]] to [[User:SHB/common.js]]: Automatically moved page while renaming the user "[[Special:CentralAuth/SHB2000|SHB2000]]" to "[[Special:CentralAuth/SHB|SHB]]"
476829
javascript
text/javascript
https://en.wikipedia.org/w/index.php?title=User:BrandonXLF/Invert.js
dr86vdcf09udfrgjt1xuokttnwd2tup
User:SHB
2
120509
762132
476830
2026-09-18T03:46:03Z
Max
57656
Max moved page [[User:SHB2000]] to [[User:SHB]]: Automatically moved page while renaming the user "[[Special:CentralAuth/SHB2000|SHB2000]]" to "[[Special:CentralAuth/SHB|SHB]]"
476830
wikitext
text/x-wiki
{{:TUT/Badge/1template}}
41qu1i3kg7ilxlferr2392lqgf8hb92
Telephone numbers in Pakistan
0
123223
762115
755005
2026-09-17T18:12:42Z
QTE-Test12-WMF
57024
/* Fixed (landline) numbers */ testing
762115
wikitext
text/x-wiki
{{short description|Wikipedia list article}}
'''Telephone numbers in Pakistan''' are ten digits long. Landline numbers and mobile numbers have different structures. Geographically fixed landline are prefixed by an area code which varies in length depending on the significance of the place. Mobile numbers are prefixed (03) followed by a code indicating the telephone operator. The international country code for Pakistan is '''<nowiki/>'+92'<nowiki/>'''.{{Infobox country telephone plan
| country = Pakistan
| country_link = Pakistan
| continent = Asia
| map_image = Pakistan (no claimed territories).svg
| map_caption = Location of Pakistan
| map_size = 220px
| map_alt =
| regulator = [[Pakistan Telecommunications Authority]]
| plan_membership =
| plan_type = Closed
| nsn_length =
| plan_link = {{URL | https://www.itu.int/oth/T02020000A1/en | National Numbering Plan Pakistan}}
| plan_date = 23 July 2010
| country_calling_code = +92
| international_prefix = 00
| trunk_prefix = 0
| codes_list =
}}
==Fixed (landline) numbers==
{{See also|List of dialling codes in Pakistan}}
Area codes in [[Pakistan]] are from two to five digits long; the smaller the city, the longer the prefix. All the large cities have two-digit codes. Test edit on ios
Smaller towns have a six digit number. Large cities have seven digit numbers. Azad Jammu and Kashmir has five digit numbers. On 1 July 2009, telephone numbers in Karachi and Lahore were changed from seven digits to eight digits. This was accomplished by adding the digit <code>9</code> to the beginning of any phone number that started with a <code>9</code> (government and semi-government connexions), and adding the digit <code>3</code> to any phone numbers that did not start with the number <code>9</code>.<ref>{{cite web | date = 2009-07-08 | title = Karachi and Lahore now have eight digit phone numbers. In the near future this will be extended to other metros. | publisher = Daily Times (Pakistan) | url = http://www.dailytimes.com.pk/default.asp?page=2009\07\08\story_8-7-2009_pg5_8
| access-date = 2009-10-01 }}</ref>
It is common to write phone numbers as '''(0xx) yyyyyyy''', where '''xx''' is the area code. The '''0''' prefix is for trunk (long-distance) dialling from within the country. International callers should dial '''+92xxyyyyyyy'''
All mobile phone codes are four digits long and start with '''03'''. All mobile numbers are seven digits long, and denote the mobile provider on a nationwide basis and not geographic location. Thus all Telenor numbers (for example) nationwide carry mobile code 0345 etc.
NWD (area) codes for common cities are:
{{columns-list|colwidth=20em|
*'''021 xxxxxxxx''': [[Karachi]]
*'''022 xxxxxxx''': [[Hyderabad, Sindh|Hyderabad]]
*'''040 xxxxxxx''': [[Sahiwal]]
*'''041 xxxxxxxx''': [[Faisalabad]]
*'''042 xxxxxxxx''': [[Lahore]]
*'''044 xxxxxxx''': [[Okara, Pakistan|Okara]]
*'''046 xxxxxxxx''': [[Toba Tek Singh]]
*'''048 xxxxxxx''': [[Sargodha]]
*'''049 xxxxxxx''': [[Kasur]]
*'''051 xxxxxxxx''': [[Islamabad]] and [[Rawalpindi]]
*'''052 xxxxxxx''': [[Sialkot]]
*'''053 xxxxxxx''': [[Gujrat city|Gujrat]]
*'''055 xxxxxxx''': [[Gujranwala]]
*'''056 xxxxxxxx''':[[Sheikhupura]]
*'''057 xxxxxxx''': [[Attock]]
*'''061 xxxxxxx''': [[Multan]]
*'''062 xxxxxxx''': [[Bahawalpur]]
*'''064 xxxxxxx''': [[Dera Ghazi Khan]]
*'''068 xxxxxxx''': [[Rahim Yar Khan]]
*'''071 xxxxxxx''': [[Sukkur]]
*'''081 xxxxxxx''': [[Quetta]]
*'''086 xxxxxxx''': [[Gwadar]]
*'''091 xxxxxxx''': [[Peshawar]]
<br/>
*'''0457 xxxxxx''': [[Arifwala]]
*'''0544 xxxxxx''': [[Jhelum]]
*'''0546 xxxxxx''': [[Mandi Bahauddin]]
*'''0606 xxxxxx''': [[Layyah]]
*'''0852 xxxxxx''': [[Turbat]] & [[Kech District]]
*'''0853 xxxxxx''':[[Lasbela District]]
*'''0855 xxxxxx''':[[Panjgur]]
*'''0926 xxxxxx''': [[Parachinar]] [[FATA]]
*'''0938 xxxxxx''': [[Swabi]]
*'''0966 xxxxxxx''': [[Dera Ismail Khan]]
*'''0992 xxxxxx''': [[Abbottabad]]
*'''0997 xxxxxx''': [[Mansehra]]
}}
Premium Rate services:<br/>*'''0900 xxxxx'''
Toll free numbers (for callers within Pakistan):<br/>*'''0800 xxxxx'''
==Mobile telephone numbers==
{{Main|List of mobile codes in Pakistan}}
Mobile telephone numbers in Pakistan are of the following format '''03XZ-YYYYYYY''' where '''X''' is the single letter code assigned to a specific mobile telephone operator and '''Z-YYYYYYY''' is the local telephone number from any mobile phone or Land Line.
*'''3''' - is the Mobile Access code
*'''Z''' can be any value between 0 and 9, assigned by the operator itself, except in case of SCOM where Z=5 only
*'''X=0''' [[Jazz Pakistan]]
*'''X=1''' [[Zong Pakistan]]
*'''X=2''' [[Jazz Pakistan]]
*'''X=3''' [[Ufone]]
*'''X=4''' [[Telenor Pakistan]]
*'''X=5''' [[Special Communications Organization|SCOM]] (Z=5 only)
*'''X=6''' [[Instaphone]]
Existing Codes
*'''300, 301, 302, 303, 304, 305, 306, 307, 308, 309''' - [[Jazz Pakistan]]
*'''310, 311, 312, 313, 314, 315, 316, 317, 318''' - [[Zong Pakistan]]
*'''320, 321, 322, 323, 324, 325, 326''' - [[Jazz Pakistan]]
*'''330, 331, 332, 333, 334, 335, 336, 337''' - [[Ufone]]
*'''340, 341, 342, 343, 344, 345, 346, 347, 348, 349''' - [[Telenor Pakistan]]
*'''355''' - [[Special Communications Organization|SCOM]]
*'''364''' - [[Instaphone]]
International callers must dial '''+92-3XZ-YYYYYYY''' to reach a mobile number in Pakistan from outside Pakistan, where ''''+92'''' is the Country Code, ''''3XZ'''' is Mobile Access Code as per the above list and ''''YYYYYYY'''' is personal number.
Within Pakistan the same number can be reached by dialing either '''03XZ-YYYYYYY''' or ''''0092-3XZ-YYYYYYY'''' or ''''+92-3XZ-YYYYYYY'''' from any mobile device or land line.
In order to dial a land line number from a mobile phone in Pakistan, city code is required in all cases. However, city code is not required between land line calls within the same city. For instance, to call a land line number ''''YYYYYYY'''' from another land line in the same city, dial only ''''YYYYYYY''''. However, to call this number from another land line in another city or from a mobile phone anywhere (same city or another city), dial ''''(0XX)-YYYYYYY''''.
Main article: List of mobile codes in Pakistan
Mobile telephone numbers in Pakistan are of the following format 03XZ-YYYYYYY where X is the single letter code assigned to a specific mobile telephone operator and Z-YYYYYYY is the local telephone number from any mobile phone or Land Line.
3 - is the Mobile Access code
Z can be any value between 0 and 9, assigned by the operator itself, except in case of SCOM where Z=5 only
X=0 Jazz Pakistan
X=1 Zong Pakistan
X=2 Jazz Pakistan
X=3 Ufone
X=4 Telenor Pakistan
X=5 SCOM (Z=5 only)
X=6 Instaphone
Existing Codes
300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - Jazz Pakistan
310, 311, 312, 313, 314, 315, 316, 317, 318 - Zong Pakistan
320, 321, 322, 323, 324, 325, 326 - Jazz Pakistan
330, 331, 332, 333, 334, 335, 336, 337 - Ufone
340, 341, 342, 343, 344, 345, 346, 347, 348, 349 - Telenor Pakistan
355 - SCOM
364 - Instaphone
International callers must dial +92-3XZ-YYYYYYY to reach a mobile number in Pakistan from outside Pakistan, where '+92' is the Country Code, '3XZ' is Mobile Access Code as per the above list and 'YYYYYYY' is personal number.
Within Pakistan the same number can be reached by dialing either 03XZ-YYYYYYY or '0092-3XZ-YYYYYYY' or '+92-3XZ-YYYYYYY' from any mobile device or land line.
In order to dial a land line number from a mobile phone in Pakistan, city code is required in all cases. However, city code is not required between land line calls within the same city. For instance, to call a land line number 'YYYYYYY' from another land line in the same city, dial only 'YYYYYYY'. However, to call this number from another land line in another city or from a mobile phone anywhere (same city or another city), dial '(0XX)-YYYYYYY'.
==References==
{{Reflist}}
*[http://www.itu.int/oth/T02020000A1/en ITU allocations list]
==External links==
* [https://ptcl.com.pk/Info/National-Dialing-Codes National Dialing Codes] {{Webarchive|url=https://web.archive.org/web/20220704204421/https://ptcl.com.pk/Info/National-Dialing-Codes |date=2022-07-04 }}
* [http://pta.gov.pk/ Pakistan Telecommunications Authority] {{Webarchive|url=https://web.archive.org/web/20171030021042/http://www.pta.gov.pk/ |date=2017-10-30 }} - Pakistan’s telephone systems regulator
{{Telephone numbers in Asia}}
[[Category:Telephone numbers in Pakistan| ]]
[[Category:Telephone numbers by country|Pakistan]]
[[Category:Pakistan communications-related lists|Telephone numbers]]<noinclude>
<small>This page was moved from [[en:Telephone numbers in Pakistan]]. Its edit history can be viewed at [[Telephone numbers in Pakistan/edithistory]]</small></noinclude>
azh5dw58l6g0yghxg7dxp2y0ix66o8x
762116
762115
2026-09-17T18:13:54Z
QTE-Test12-WMF
57024
/* Fixed (landline) numbers */ Test android
762116
wikitext
text/x-wiki
{{short description|Wikipedia list article}}
'''Telephone numbers in Pakistan''' are ten digits long. Landline numbers and mobile numbers have different structures. Geographically fixed landline are prefixed by an area code which varies in length depending on the significance of the place. Mobile numbers are prefixed (03) followed by a code indicating the telephone operator. The international country code for Pakistan is '''<nowiki/>'+92'<nowiki/>'''.{{Infobox country telephone plan
| country = Pakistan
| country_link = Pakistan
| continent = Asia
| map_image = Pakistan (no claimed territories).svg
| map_caption = Location of Pakistan
| map_size = 220px
| map_alt =
| regulator = [[Pakistan Telecommunications Authority]]
| plan_membership =
| plan_type = Closed
| nsn_length =
| plan_link = {{URL | https://www.itu.int/oth/T02020000A1/en | National Numbering Plan Pakistan}}
| plan_date = 23 July 2010
| country_calling_code = +92
| international_prefix = 00
| trunk_prefix = 0
| codes_list =
}}
==Fixed (landline) numbers==
{{See also|List of dialling codes in Pakistan}}
Area codes in [[Pakistan]] are from two to five digits long; the smaller the city, the longer the prefix. All the large cities have two-digit codes. Test edit on android
Smaller towns have a six digit number. Large cities have seven digit numbers. Azad Jammu and Kashmir has five digit numbers. On 1 July 2009, telephone numbers in Karachi and Lahore were changed from seven digits to eight digits. This was accomplished by adding the digit <code>9</code> to the beginning of any phone number that started with a <code>9</code> (government and semi-government connexions), and adding the digit <code>3</code> to any phone numbers that did not start with the number <code>9</code>.<ref>{{cite web | date = 2009-07-08 | title = Karachi and Lahore now have eight digit phone numbers. In the near future this will be extended to other metros. | publisher = Daily Times (Pakistan) | url = http://www.dailytimes.com.pk/default.asp?page=2009\07\08\story_8-7-2009_pg5_8
| access-date = 2009-10-01 }}</ref>
It is common to write phone numbers as '''(0xx) yyyyyyy''', where '''xx''' is the area code. The '''0''' prefix is for trunk (long-distance) dialling from within the country. International callers should dial '''+92xxyyyyyyy'''
All mobile phone codes are four digits long and start with '''03'''. All mobile numbers are seven digits long, and denote the mobile provider on a nationwide basis and not geographic location. Thus all Telenor numbers (for example) nationwide carry mobile code 0345 etc.
NWD (area) codes for common cities are:
{{columns-list|colwidth=20em|
*'''021 xxxxxxxx''': [[Karachi]]
*'''022 xxxxxxx''': [[Hyderabad, Sindh|Hyderabad]]
*'''040 xxxxxxx''': [[Sahiwal]]
*'''041 xxxxxxxx''': [[Faisalabad]]
*'''042 xxxxxxxx''': [[Lahore]]
*'''044 xxxxxxx''': [[Okara, Pakistan|Okara]]
*'''046 xxxxxxxx''': [[Toba Tek Singh]]
*'''048 xxxxxxx''': [[Sargodha]]
*'''049 xxxxxxx''': [[Kasur]]
*'''051 xxxxxxxx''': [[Islamabad]] and [[Rawalpindi]]
*'''052 xxxxxxx''': [[Sialkot]]
*'''053 xxxxxxx''': [[Gujrat city|Gujrat]]
*'''055 xxxxxxx''': [[Gujranwala]]
*'''056 xxxxxxxx''':[[Sheikhupura]]
*'''057 xxxxxxx''': [[Attock]]
*'''061 xxxxxxx''': [[Multan]]
*'''062 xxxxxxx''': [[Bahawalpur]]
*'''064 xxxxxxx''': [[Dera Ghazi Khan]]
*'''068 xxxxxxx''': [[Rahim Yar Khan]]
*'''071 xxxxxxx''': [[Sukkur]]
*'''081 xxxxxxx''': [[Quetta]]
*'''086 xxxxxxx''': [[Gwadar]]
*'''091 xxxxxxx''': [[Peshawar]]
<br/>
*'''0457 xxxxxx''': [[Arifwala]]
*'''0544 xxxxxx''': [[Jhelum]]
*'''0546 xxxxxx''': [[Mandi Bahauddin]]
*'''0606 xxxxxx''': [[Layyah]]
*'''0852 xxxxxx''': [[Turbat]] & [[Kech District]]
*'''0853 xxxxxx''':[[Lasbela District]]
*'''0855 xxxxxx''':[[Panjgur]]
*'''0926 xxxxxx''': [[Parachinar]] [[FATA]]
*'''0938 xxxxxx''': [[Swabi]]
*'''0966 xxxxxxx''': [[Dera Ismail Khan]]
*'''0992 xxxxxx''': [[Abbottabad]]
*'''0997 xxxxxx''': [[Mansehra]]
}}
Premium Rate services:<br/>*'''0900 xxxxx'''
Toll free numbers (for callers within Pakistan):<br/>*'''0800 xxxxx'''
==Mobile telephone numbers==
{{Main|List of mobile codes in Pakistan}}
Mobile telephone numbers in Pakistan are of the following format '''03XZ-YYYYYYY''' where '''X''' is the single letter code assigned to a specific mobile telephone operator and '''Z-YYYYYYY''' is the local telephone number from any mobile phone or Land Line.
*'''3''' - is the Mobile Access code
*'''Z''' can be any value between 0 and 9, assigned by the operator itself, except in case of SCOM where Z=5 only
*'''X=0''' [[Jazz Pakistan]]
*'''X=1''' [[Zong Pakistan]]
*'''X=2''' [[Jazz Pakistan]]
*'''X=3''' [[Ufone]]
*'''X=4''' [[Telenor Pakistan]]
*'''X=5''' [[Special Communications Organization|SCOM]] (Z=5 only)
*'''X=6''' [[Instaphone]]
Existing Codes
*'''300, 301, 302, 303, 304, 305, 306, 307, 308, 309''' - [[Jazz Pakistan]]
*'''310, 311, 312, 313, 314, 315, 316, 317, 318''' - [[Zong Pakistan]]
*'''320, 321, 322, 323, 324, 325, 326''' - [[Jazz Pakistan]]
*'''330, 331, 332, 333, 334, 335, 336, 337''' - [[Ufone]]
*'''340, 341, 342, 343, 344, 345, 346, 347, 348, 349''' - [[Telenor Pakistan]]
*'''355''' - [[Special Communications Organization|SCOM]]
*'''364''' - [[Instaphone]]
International callers must dial '''+92-3XZ-YYYYYYY''' to reach a mobile number in Pakistan from outside Pakistan, where ''''+92'''' is the Country Code, ''''3XZ'''' is Mobile Access Code as per the above list and ''''YYYYYYY'''' is personal number.
Within Pakistan the same number can be reached by dialing either '''03XZ-YYYYYYY''' or ''''0092-3XZ-YYYYYYY'''' or ''''+92-3XZ-YYYYYYY'''' from any mobile device or land line.
In order to dial a land line number from a mobile phone in Pakistan, city code is required in all cases. However, city code is not required between land line calls within the same city. For instance, to call a land line number ''''YYYYYYY'''' from another land line in the same city, dial only ''''YYYYYYY''''. However, to call this number from another land line in another city or from a mobile phone anywhere (same city or another city), dial ''''(0XX)-YYYYYYY''''.
Main article: List of mobile codes in Pakistan
Mobile telephone numbers in Pakistan are of the following format 03XZ-YYYYYYY where X is the single letter code assigned to a specific mobile telephone operator and Z-YYYYYYY is the local telephone number from any mobile phone or Land Line.
3 - is the Mobile Access code
Z can be any value between 0 and 9, assigned by the operator itself, except in case of SCOM where Z=5 only
X=0 Jazz Pakistan
X=1 Zong Pakistan
X=2 Jazz Pakistan
X=3 Ufone
X=4 Telenor Pakistan
X=5 SCOM (Z=5 only)
X=6 Instaphone
Existing Codes
300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - Jazz Pakistan
310, 311, 312, 313, 314, 315, 316, 317, 318 - Zong Pakistan
320, 321, 322, 323, 324, 325, 326 - Jazz Pakistan
330, 331, 332, 333, 334, 335, 336, 337 - Ufone
340, 341, 342, 343, 344, 345, 346, 347, 348, 349 - Telenor Pakistan
355 - SCOM
364 - Instaphone
International callers must dial +92-3XZ-YYYYYYY to reach a mobile number in Pakistan from outside Pakistan, where '+92' is the Country Code, '3XZ' is Mobile Access Code as per the above list and 'YYYYYYY' is personal number.
Within Pakistan the same number can be reached by dialing either 03XZ-YYYYYYY or '0092-3XZ-YYYYYYY' or '+92-3XZ-YYYYYYY' from any mobile device or land line.
In order to dial a land line number from a mobile phone in Pakistan, city code is required in all cases. However, city code is not required between land line calls within the same city. For instance, to call a land line number 'YYYYYYY' from another land line in the same city, dial only 'YYYYYYY'. However, to call this number from another land line in another city or from a mobile phone anywhere (same city or another city), dial '(0XX)-YYYYYYY'.
==References==
{{Reflist}}
*[http://www.itu.int/oth/T02020000A1/en ITU allocations list]
==External links==
* [https://ptcl.com.pk/Info/National-Dialing-Codes National Dialing Codes] {{Webarchive|url=https://web.archive.org/web/20220704204421/https://ptcl.com.pk/Info/National-Dialing-Codes |date=2022-07-04 }}
* [http://pta.gov.pk/ Pakistan Telecommunications Authority] {{Webarchive|url=https://web.archive.org/web/20171030021042/http://www.pta.gov.pk/ |date=2017-10-30 }} - Pakistan’s telephone systems regulator
{{Telephone numbers in Asia}}
[[Category:Telephone numbers in Pakistan| ]]
[[Category:Telephone numbers by country|Pakistan]]
[[Category:Pakistan communications-related lists|Telephone numbers]]<noinclude>
<small>This page was moved from [[en:Telephone numbers in Pakistan]]. Its edit history can be viewed at [[Telephone numbers in Pakistan/edithistory]]</small></noinclude>
1qo28slrbq64o1swvzcs1zm6302bzv8
762117
762116
2026-09-17T18:14:50Z
~2026-50203-97
75692
Fixed typo
762117
wikitext
text/x-wiki
{{short description|Wikipedia list article}}
'''Telephone numbers in Pakistan''' are ten digits long. Landline numbers and mobile numbers have different structures. Geographically fixed landline are prefixed by an area code which varies in length depending on the significance of the place. Mobile numbers are prefixed (03) followed by a code indicating the telephone operator. TEST edit on iOS. The international country code for Pakistan is '''<nowiki/>'+92'<nowiki/>'''.{{Infobox country telephone plan
| country = Pakistan
| country_link = Pakistan
| continent = Asia
| map_image = Pakistan (no claimed territories).svg
| map_caption = Location of Pakistan
| map_size = 220px
| map_alt =
| regulator = [[Pakistan Telecommunications Authority]]
| plan_membership =
| plan_type = Closed
| nsn_length =
| plan_link = {{URL | https://www.itu.int/oth/T02020000A1/en | National Numbering Plan Pakistan}}
| plan_date = 23 July 2010
| country_calling_code = +92
| international_prefix = 00
| trunk_prefix = 0
| codes_list =
}}
==Fixed (landline) numbers==
{{See also|List of dialling codes in Pakistan}}
Area codes in [[Pakistan]] are from two to five digits long; the smaller the city, the longer the prefix. All the large cities have two-digit codes. Test edit on android
Smaller towns have a six digit number. Large cities have seven digit numbers. Azad Jammu and Kashmir has five digit numbers. On 1 July 2009, telephone numbers in Karachi and Lahore were changed from seven digits to eight digits. This was accomplished by adding the digit <code>9</code> to the beginning of any phone number that started with a <code>9</code> (government and semi-government connexions), and adding the digit <code>3</code> to any phone numbers that did not start with the number <code>9</code>.<ref>{{cite web | date = 2009-07-08 | title = Karachi and Lahore now have eight digit phone numbers. In the near future this will be extended to other metros. | publisher = Daily Times (Pakistan) | url = http://www.dailytimes.com.pk/default.asp?page=2009\07\08\story_8-7-2009_pg5_8
| access-date = 2009-10-01 }}</ref>
It is common to write phone numbers as '''(0xx) yyyyyyy''', where '''xx''' is the area code. The '''0''' prefix is for trunk (long-distance) dialling from within the country. International callers should dial '''+92xxyyyyyyy'''
All mobile phone codes are four digits long and start with '''03'''. All mobile numbers are seven digits long, and denote the mobile provider on a nationwide basis and not geographic location. Thus all Telenor numbers (for example) nationwide carry mobile code 0345 etc.
NWD (area) codes for common cities are:
{{columns-list|colwidth=20em|
*'''021 xxxxxxxx''': [[Karachi]]
*'''022 xxxxxxx''': [[Hyderabad, Sindh|Hyderabad]]
*'''040 xxxxxxx''': [[Sahiwal]]
*'''041 xxxxxxxx''': [[Faisalabad]]
*'''042 xxxxxxxx''': [[Lahore]]
*'''044 xxxxxxx''': [[Okara, Pakistan|Okara]]
*'''046 xxxxxxxx''': [[Toba Tek Singh]]
*'''048 xxxxxxx''': [[Sargodha]]
*'''049 xxxxxxx''': [[Kasur]]
*'''051 xxxxxxxx''': [[Islamabad]] and [[Rawalpindi]]
*'''052 xxxxxxx''': [[Sialkot]]
*'''053 xxxxxxx''': [[Gujrat city|Gujrat]]
*'''055 xxxxxxx''': [[Gujranwala]]
*'''056 xxxxxxxx''':[[Sheikhupura]]
*'''057 xxxxxxx''': [[Attock]]
*'''061 xxxxxxx''': [[Multan]]
*'''062 xxxxxxx''': [[Bahawalpur]]
*'''064 xxxxxxx''': [[Dera Ghazi Khan]]
*'''068 xxxxxxx''': [[Rahim Yar Khan]]
*'''071 xxxxxxx''': [[Sukkur]]
*'''081 xxxxxxx''': [[Quetta]]
*'''086 xxxxxxx''': [[Gwadar]]
*'''091 xxxxxxx''': [[Peshawar]]
<br/>
*'''0457 xxxxxx''': [[Arifwala]]
*'''0544 xxxxxx''': [[Jhelum]]
*'''0546 xxxxxx''': [[Mandi Bahauddin]]
*'''0606 xxxxxx''': [[Layyah]]
*'''0852 xxxxxx''': [[Turbat]] & [[Kech District]]
*'''0853 xxxxxx''':[[Lasbela District]]
*'''0855 xxxxxx''':[[Panjgur]]
*'''0926 xxxxxx''': [[Parachinar]] [[FATA]]
*'''0938 xxxxxx''': [[Swabi]]
*'''0966 xxxxxxx''': [[Dera Ismail Khan]]
*'''0992 xxxxxx''': [[Abbottabad]]
*'''0997 xxxxxx''': [[Mansehra]]
}}
Premium Rate services:<br/>*'''0900 xxxxx'''
Toll free numbers (for callers within Pakistan):<br/>*'''0800 xxxxx'''
==Mobile telephone numbers==
{{Main|List of mobile codes in Pakistan}}
Mobile telephone numbers in Pakistan are of the following format '''03XZ-YYYYYYY''' where '''X''' is the single letter code assigned to a specific mobile telephone operator and '''Z-YYYYYYY''' is the local telephone number from any mobile phone or Land Line.
*'''3''' - is the Mobile Access code
*'''Z''' can be any value between 0 and 9, assigned by the operator itself, except in case of SCOM where Z=5 only
*'''X=0''' [[Jazz Pakistan]]
*'''X=1''' [[Zong Pakistan]]
*'''X=2''' [[Jazz Pakistan]]
*'''X=3''' [[Ufone]]
*'''X=4''' [[Telenor Pakistan]]
*'''X=5''' [[Special Communications Organization|SCOM]] (Z=5 only)
*'''X=6''' [[Instaphone]]
Existing Codes
*'''300, 301, 302, 303, 304, 305, 306, 307, 308, 309''' - [[Jazz Pakistan]]
*'''310, 311, 312, 313, 314, 315, 316, 317, 318''' - [[Zong Pakistan]]
*'''320, 321, 322, 323, 324, 325, 326''' - [[Jazz Pakistan]]
*'''330, 331, 332, 333, 334, 335, 336, 337''' - [[Ufone]]
*'''340, 341, 342, 343, 344, 345, 346, 347, 348, 349''' - [[Telenor Pakistan]]
*'''355''' - [[Special Communications Organization|SCOM]]
*'''364''' - [[Instaphone]]
International callers must dial '''+92-3XZ-YYYYYYY''' to reach a mobile number in Pakistan from outside Pakistan, where ''''+92'''' is the Country Code, ''''3XZ'''' is Mobile Access Code as per the above list and ''''YYYYYYY'''' is personal number.
Within Pakistan the same number can be reached by dialing either '''03XZ-YYYYYYY''' or ''''0092-3XZ-YYYYYYY'''' or ''''+92-3XZ-YYYYYYY'''' from any mobile device or land line.
In order to dial a land line number from a mobile phone in Pakistan, city code is required in all cases. However, city code is not required between land line calls within the same city. For instance, to call a land line number ''''YYYYYYY'''' from another land line in the same city, dial only ''''YYYYYYY''''. However, to call this number from another land line in another city or from a mobile phone anywhere (same city or another city), dial ''''(0XX)-YYYYYYY''''.
Main article: List of mobile codes in Pakistan
Mobile telephone numbers in Pakistan are of the following format 03XZ-YYYYYYY where X is the single letter code assigned to a specific mobile telephone operator and Z-YYYYYYY is the local telephone number from any mobile phone or Land Line.
3 - is the Mobile Access code
Z can be any value between 0 and 9, assigned by the operator itself, except in case of SCOM where Z=5 only
X=0 Jazz Pakistan
X=1 Zong Pakistan
X=2 Jazz Pakistan
X=3 Ufone
X=4 Telenor Pakistan
X=5 SCOM (Z=5 only)
X=6 Instaphone
Existing Codes
300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - Jazz Pakistan
310, 311, 312, 313, 314, 315, 316, 317, 318 - Zong Pakistan
320, 321, 322, 323, 324, 325, 326 - Jazz Pakistan
330, 331, 332, 333, 334, 335, 336, 337 - Ufone
340, 341, 342, 343, 344, 345, 346, 347, 348, 349 - Telenor Pakistan
355 - SCOM
364 - Instaphone
International callers must dial +92-3XZ-YYYYYYY to reach a mobile number in Pakistan from outside Pakistan, where '+92' is the Country Code, '3XZ' is Mobile Access Code as per the above list and 'YYYYYYY' is personal number.
Within Pakistan the same number can be reached by dialing either 03XZ-YYYYYYY or '0092-3XZ-YYYYYYY' or '+92-3XZ-YYYYYYY' from any mobile device or land line.
In order to dial a land line number from a mobile phone in Pakistan, city code is required in all cases. However, city code is not required between land line calls within the same city. For instance, to call a land line number 'YYYYYYY' from another land line in the same city, dial only 'YYYYYYY'. However, to call this number from another land line in another city or from a mobile phone anywhere (same city or another city), dial '(0XX)-YYYYYYY'.
==References==
{{Reflist}}
*[http://www.itu.int/oth/T02020000A1/en ITU allocations list]
==External links==
* [https://ptcl.com.pk/Info/National-Dialing-Codes National Dialing Codes] {{Webarchive|url=https://web.archive.org/web/20220704204421/https://ptcl.com.pk/Info/National-Dialing-Codes |date=2022-07-04 }}
* [http://pta.gov.pk/ Pakistan Telecommunications Authority] {{Webarchive|url=https://web.archive.org/web/20171030021042/http://www.pta.gov.pk/ |date=2017-10-30 }} - Pakistan’s telephone systems regulator
{{Telephone numbers in Asia}}
[[Category:Telephone numbers in Pakistan| ]]
[[Category:Telephone numbers by country|Pakistan]]
[[Category:Pakistan communications-related lists|Telephone numbers]]<noinclude>
<small>This page was moved from [[en:Telephone numbers in Pakistan]]. Its edit history can be viewed at [[Telephone numbers in Pakistan/edithistory]]</small></noinclude>
hop0chi0r0k6ul2pm1vxuodgrouuc0g
User:SongVĩ.Bot II
2
124239
762111
762033
2026-09-17T17:00:23Z
SongVĩ.Bot II
52414
[[User:SongVĩ.Bot II|Task 0]]: Đã 1725 ngày...
762111
wikitext
text/x-wiki
Cập nhật lần cuối: 18-09-2026
Đã 1725 ngày...
apcpc1sautl8a1giqrebik3geqq7adr
Natuurlike omgewing
0
146009
762107
541235
2026-09-17T14:36:13Z
SGimeno (WMF)
51965
762107
wikitext
text/x-wiki
== Natuurlike omgewing ==
Test lead section and some more text
8axoi619ufmu9cdpb5voeb4tgtevhsq
Wikipedia:Village pump/topic list
4
146208
762152
761513
2026-09-18T08:46:02Z
Cewbot
33876
[[User:Cewbot/log/20170915/configuration|Generate topic list: 14 topics]]
762152
wikitext
text/x-wiki
<!-- This page is auto-generated by bot. Please contact the bot operator to improve the tool. -->
{| class="wikitable sortable mw-collapsible" style="float:left;"
|-
! data-sort-type="number" style="font-weight: normal;" | <small>#</small> !! 💭 Title !! <span title="Count of comments">💬</span> !! <span title="Count of peoples in discussion">👥</span> !! 🙋 Last editor !! data-sort-type="isoDate" | <span title="Date/Time">🕒 <small>(UTC)</small></span>
|-
| style="text-align: right;" | 1
| [[Wikipedia:Village pump#Script|Script]]
| style="text-align: right;" | 8
| style="text-align: right;" | 5
| style="background-color: #bbb;" | [[User:LuniZunie|LuniZunie]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2025-11-09T16:47:00.000Z" | 2025-11-09 <span style="color: blue;">16:47</span>
|-
| style="text-align: right;" | 2
| [[Wikipedia:Village pump#Report_concerning_Tanbiruzzammn|Report concerning Tanbiruzzammn]]
| style="text-align: right;" | 2
| style="text-align: right;" | 2
| style="background-color: #bbb;" | [[User:Barras|Barras]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2025-12-09T21:45:00.000Z" | 2025-12-09 <span style="color: blue;">21:45</span>
|-
| style="text-align: right;" | 3
| [[Wikipedia:Village pump#Report_concerning_Bucheon|Report concerning Bucheon]]
| style="text-align: right;background-color: #fcc;" | 1
| style="text-align: right;background-color: #fcc;" | 1
| style="background-color: #bbb;" | [[User:PieWriter|PieWriter]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2026-02-19T10:25:00.000Z" | 2026-02-19 <span style="color: blue;">10:25</span>
|-
| style="text-align: right;" | 4
| [[Wikipedia:Village pump#Versions_and_dates|Versions and dates]]
| style="text-align: right;" | 2
| style="text-align: right;background-color: #fcc;" | 1
| style="background-color: #bbb;" | [[Special:Contributions/~2026-13668-13|<span style="color: #c20;">~2026-13668-13</span>]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2026-03-03T06:17:00.000Z" | 2026-03-03 <span style="color: blue;">06:17</span>
|-
| style="text-align: right;" | 5
| style="max-width: 24em" | <small>[[Wikipedia:Village pump#Upcoming_Wikimedia_Café_meetup_regarding_the_the_2026-2027_Wikimedia_Foundation_Annual_Plan|Upcoming Wikimedia Café meetup regarding the the 2026-2027 Wikimedia Foundation Annual Plan]]</small>
| style="text-align: right;background-color: #fcc;" | 1
| style="text-align: right;background-color: #fcc;" | 1
| style="background-color: #bbb;" | [[User:Pine|Pine]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2026-03-30T03:46:00.000Z" | 2026-03-30 <span style="color: blue;">03:46</span>
|-
| style="text-align: right;" | 6
| [[Wikipedia:Village pump#Changes_to_electionadmin_userright|Changes to electionadmin userright]]
| style="text-align: right;" | 4
| style="text-align: right;" | 4
| style="background-color: #bbb;" | [[User:Chaotic Enby|Chaotic Enby]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2026-04-23T15:22:00.000Z" | 2026-04-23 <span style="color: blue;">15:22</span>
|-
| style="text-align: right;" | 7
| style="max-width: 24em" | <small>[[Wikipedia:Village pump#Report_concerning_Princebarackalibarrydaddyobamaiii|Report concerning Princebarackalibarrydaddyobamaiii]]</small>
| style="text-align: right;background-color: #fcc;" | 1
| style="text-align: right;background-color: #fcc;" | 1
| style="background-color: #bbb;" | [[User:MathXplore|MathXplore]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2026-05-18T12:23:00.000Z" | 2026-05-18 <span style="color: blue;">12:23</span>
|-
| style="text-align: right;" | 8
| style="max-width: 24em" | <small>[[Wikipedia:Village pump#May_2026_Wikimedia_Café_meetups_regarding_the_Wikimedia_Foundation_Annual_Plan|May 2026 Wikimedia Café meetups regarding the Wikimedia Foundation Annual Plan]]</small>
| style="text-align: right;background-color: #fcc;" | 1
| style="text-align: right;background-color: #fcc;" | 1
| style="background-color: #bbb;" | [[User:Pine|Pine]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2026-05-21T19:54:00.000Z" | 2026-05-21 <span style="color: blue;">19:54</span>
|-
| style="text-align: right;" | 9
| style="max-width: 24em" | <small>[[Wikipedia:Village pump#June_2026_Wikimedia_Café_meetups_regarding_the_English_Wikipedia_Editor_Reflections_project|June 2026 Wikimedia Café meetups regarding the English Wikipedia Editor Reflections project]]</small>
| style="text-align: right;background-color: #fcc;" | 1
| style="text-align: right;background-color: #fcc;" | 1
| style="background-color: #bbb;" | [[User:Pine|Pine]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2026-06-15T03:56:00.000Z" | 2026-06-15 <span style="color: blue;">03:56</span>
|-
| style="text-align: right;" | 10
| [[Wikipedia:Village pump#Removal_request|Removal request]]
| style="text-align: right;" | 2
| style="text-align: right;" | 2
| style="background-color: #bbb;" | [[User:Vermont|Vermont]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2026-07-05T20:08:00.000Z" | 2026-07-05 <span style="color: blue;">20:08</span>
|-
| style="text-align: right;" | 11
| style="max-width: 24em" | <small>[[Wikipedia:Village pump#July_2026_Wikimedia_Café_meetups_regarding_Wikimedia_governance_and_options_for_reform|July 2026 Wikimedia Café meetups regarding Wikimedia governance and options for reform]]</small>
| style="text-align: right;background-color: #fcc;" | 1
| style="text-align: right;background-color: #fcc;" | 1
| style="background-color: #bbb;" | [[User:Pine|Pine]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2026-07-13T03:35:00.000Z" | 2026-07-13 <span style="color: blue;">03:35</span>
|-
| style="text-align: right;" | 12
| [[Wikipedia:Village pump#Spambot|Spambot]]
| style="text-align: right;" | 2
| style="text-align: right;" | 2
| style="background-color: #bbb;" | [[User:BDavis (WMF)|BDavis (WMF)]]
| style="background-color: #bbb;" data-sort-type="isoDate" data-sort-value="2026-07-23T00:30:00.000Z" | 2026-07-23 <span style="color: blue;">00:30</span>
|-
| style="text-align: right;" | 13
| style="max-width: 24em" | <small>[[Wikipedia:Village pump#Adding_some_local_content_pages_for_Pretrain_project_testing|Adding some local content pages for Pretrain project testing]]</small>
| style="text-align: right;" | 8
| style="text-align: right;" | 4
| style="background-color: #ddd;" | [[User:BDavis (WMF)|BDavis (WMF)]]
| style="background-color: #ddd;" data-sort-type="isoDate" data-sort-value="2026-08-28T20:41:00.000Z" | 2026-08-28 <span style="color: blue;">20:41</span>
|-
| style="text-align: right;" | 14
| [[Wikipedia:Village pump#This_Month_in_GLAM:_August_2026|''This Month in GLAM'': August 2026]]
| style="text-align: right;background-color: #fcc;" | 1
| style="text-align: right;background-color: #fcc;" | 1
| style="background-color: #ddd;" | [[User:Romaine|Romaine]]
| style="background-color: #ddd;" data-sort-type="isoDate" data-sort-value="2026-09-11T08:36:00.000Z" | 2026-09-11 <span style="color: blue;">08:36</span>
|}
{| class="wikitable mw-collapsible mw-collapsed" style="float: left; margin-left: .5em;;{{#if:{{{no_time_legend|}}}|display:none;|}}"
! title="From the latest bot edit" | Legend
|-
| style="background-color: #efe;" |
* In the last hour
|-
| style="background-color: #eef;" |
* In the last day
|-
| |
* In the last week
|-
| style="background-color: #ddd;" |
* In the last month
|-
| style="background-color: #bbb;" |
* More than one month
|-
! Manual settings
|-
| style="max-width: 12em;" | <small>When exceptions occur,<br />please check [[User:Cewbot/log/20170915/configuration|the setting]] first.</small>
|-
|}
{{Clear}}
tdzm26rr0j76y11w7z35yhzuc4jxmch
User:DWalden (WMF)/common.js
2
147574
762154
595050
2026-09-18T10:35:12Z
DWalden (WMF)
44719
762154
javascript
text/javascript
// foobar
12dxkn8ofciyhxxlagynws43jqxni25
762155
762154
2026-09-18T10:35:27Z
DWalden (WMF)
44719
Undid revision [[Special:Diff/762154|762154]] by [[Special:Contributions/DWalden (WMF)|DWalden (WMF)]] ([[User talk:DWalden (WMF)|talk]])
762155
javascript
text/javascript
phoiac9h4m842xq45sp7s6u21eteeq1
User:Msz2001/sandbox
2
166438
762108
749151
2026-09-17T15:04:34Z
Msz2001
40565
762108
wikitext
text/x-wiki
Lorem ipsum dolor sit amet
Test
rihb8fwf7iy9ar5f2k8t5awv8fpmed4
762109
762108
2026-09-17T15:06:47Z
Msz2001
40565
762109
wikitext
text/x-wiki
Lorem ipsum dolor sit amet
Test 123
ikuy2h2owsrmahcfvqfpg9nj0szxz20
User:Qooimi/sandbox
2
174012
762162
732931
2026-09-18T11:47:40Z
Cabayi
3052
Cabayi moved page [[User:Ioannis Kouimoutzoglou/sandbox]] to [[User:Qooimi/sandbox]]: Automatically moved page while renaming the user "[[Special:CentralAuth/Ioannis Kouimoutzoglou|Ioannis Kouimoutzoglou]]" to "[[Special:CentralAuth/Qooimi|Qooimi]]"
732931
wikitext
text/x-wiki
[[Category:Buildings and structures in Greece]]
jmi9ijfkas2f4tyn2ohhnl4mo6nmefh
User:Namoroka/sandbox/7
2
177925
762106
757932
2026-09-17T13:45:02Z
Namoroka
19627
762106
wikitext
text/x-wiki
{{절차 머리말
| 제목 = 옛한글 입력 도구
| 부제 =
| 이전 =
| 다음 =
| 단축 =
| 설명 =
}}
'''옛한글 입력 도구'''는 편집창 등에서 [[위키문헌:옛한글|옛한글]]을 입력할 수 있도록 도와주는 자바스크립트 소도구입니다.
bab2min가 개발한 [https://akorn.bab2min.pe.kr/input/ 어듸메 옛한글 입력기]를 기반으로 합니다.
== 사용법 ==
=== 활성화 ===
[[특수:환경설정]] → [[특수:환경설정#mw-prefsection-gadgets|소도구]] → 옛한글 입력 도구에서 활성화 가능합니다.
입력기는 아래 방법 중 하나를 사용하여 켜고 끌 수 있습니다.
* [[w:위키백과:편집 도구 모음|편집 도구 모음]]에서 "[[파일:OOjs UI icon yethangul.svg|20px|class=skin-invert]] '''옛한글'''" 버튼 클릭
* 도구 메뉴(사이드바) → "옛한글 입력 켜기/끄기" 클릭
* 단축키 {{키눌림|Ctrl}} + {{키눌림|Shift}} + {{키눌림|f}}
활성화 이후에는 다시 위 방법을 이용하여 해제하지 않는 이상 활성화 상태가 유지됩니다. 편집창 뿐만이 아닌 검색창, 편집 요약 등에서도 입력 기능이 유지됩니다.
대한민국 표준 두벌식 자판(KS X 5002)에서의 사용을 전제로 합니다.
=== 입력 방법 ===
* {{옛한글 인라인|ㅿ}}: {{키눌림|Shift}} + {{키눌림|ㅁ}} (혹은 {{키눌림|ㅁ}} + {{키눌림|.}})
* {{옛한글 인라인|ㆁ}}: {{키눌림|Shift}} + {{키눌림|ㅇ}} (혹은 {{키눌림|ㅇ}} + {{키눌림|.}})
* {{옛한글 인라인|ㆆ}}: {{키눌림|Shift}} + {{키눌림|ㅎ}} (혹은 {{키눌림|ㅎ}} + {{키눌림|.}})
* {{옛한글 인라인|ᄼ}}: {{키눌림|Shift}} + {{키눌림|ㅋ}} (혹은 {{키눌림|ㅋ}} + {{키눌림|.}})
* {{옛한글 인라인|ᄾ}}: {{키눌림|Shift}} + {{키눌림|ㅌ}} (혹은 {{키눌림|ㅌ}} + {{키눌림|.}})
* {{옛한글 인라인|ᅎ}}: {{키눌림|Shift}} + {{키눌림|ㅊ}} (혹은 {{키눌림|ㅊ}} + {{키눌림|.}})
* {{옛한글 인라인|ᅐ}}: {{키눌림|Shift}} + {{키눌림|ㅍ}} (혹은 {{키눌림|ㅍ}} + {{키눌림|.}})
* {{옛한글 인라인|ᅔ}}: {{키눌림|Shift}} + {{키눌림|ㅠ}} (혹은 {{키눌림|ㅠ}} + {{키눌림|.}})
* {{옛한글 인라인|ᅕ}}: {{키눌림|Shift}} + {{키눌림|ㅜ}} (혹은 {{키눌림|ㅜ}} + {{키눌림|.}})
* {{옛한글 인라인|ᄽ}}: {{키눌림|Shift}} + {{키눌림|ㅋ}} + {{키눌림|ㅋ}} (혹은 {{키눌림|ㅋ}} + {{키눌림|.}} + {{키눌림|.}})
* {{옛한글 인라인|ᄿ}}: {{키눌림|Shift}} + {{키눌림|ㅌ}} + {{키눌림|ㅌ}} (혹은 {{키눌림|ㅌ}} + {{키눌림|.}} + {{키눌림|.}})
* {{옛한글 인라인|ᅏ}}: {{키눌림|Shift}} + {{키눌림|ㅊ}} + {{키눌림|ㅊ}} (혹은 {{키눌림|ㅊ}} + {{키눌림|.}} + {{키눌림|.}})
* {{옛한글 인라인|ᅑ}}: {{키눌림|Shift}} + {{키눌림|ㅍ}} + {{키눌림|ㅍ}} (혹은 {{키눌림|ㅍ}} + {{키눌림|.}} + {{키눌림|.}})
* {{옛한글 인라인|ㆍ}}: {{키눌림|ㅏ}} + {{키눌림|ㅏ}}
* 합용/각자 병서: 각 자음 혹은 모음을 순서대로 입력
== 입력 지원 범위 ==
아래의 자모를 지원합니다.
*초성: {{옛한글 인라인|ᄀ ᄁ ᄂ ᄃ ᄄ ᄅ ᄆ ᄇ ᄈ ᄉ ᄊ ᄋ ᄌ ᄍ ᄎ ᄏ ᄐ ᄑ ᄒ ᄓ ᄔ ᄕ ᄖ ᄗ ᄘ ᄙ ᄚ ᄛ ᄜ ᄝ ᄞ ᄟ ᄠ ᄡ ᄢ ᄣ ᄤ ᄥ ᄦ ᄧ ᄨ ᄩ ᄪ ᄫ ᄬ ᄭ ᄮ ᄯ ᄰ ᄱ ᄲ ᄳ ᄴ ᄵ ᄶ ᄷ ᄸ ᄹ ᄺ ᄻ ᄼ ᄽ ᄾ ᄿ ᅀ ᅁ ᅂ ᅃ ᅄ ᅅ ᅆ ᅇ ᅈ ᅉ ᅊ ᅋ ᅌ ᅍ ᅎ ᅏ ᅐ ᅑ ᅒ ᅓ ᅔ ᅕ ᅖ ᅗ ᅘ ᅙ ᅚ ᅛ ᅜ ᅝ ᅞ ꥠ ꥡ ꥢ ꥣ ꥤ ꥥ ꥦ ꥧ ꥨ ꥩ ꥪ ꥫ ꥬ ꥭ ꥮ ꥯ ꥰ ꥱ ꥲ ꥳ ꥴ ꥵ ꥶ ꥷ ꥸ ꥹ ꥺ ꥻ ꥼ}}
*중성: {{옛한글 인라인|ᅡ ᅢ ᅣ ᅤ ᅥ ᅦ ᅧ ᅨ ᅩ ᅪ ᅫ ᅬ ᅭ ᅮ ᅯ ᅰ ᅱ ᅲ ᅳ ᅴ ᅵ ᅶ ᅷ ᅸ ᅹ ᅺ ᅻ ᅼ ᅽ ᅾ ᅿ ᆀ ᆁ ᆂ ᆃ ᆄ ᆅ ᆆ ᆇ ᆈ ᆉ ᆊ ᆋ ᆌ ᆍ ᆎ ᆏ ᆐ ᆑ ᆒ ᆓ ᆔ ᆕ ᆖ ᆗ ᆘ ᆙ ᆚ ᆛ ᆜ ᆝ ᆞ ᆟ ᆠ ᆡ ᆢ ᆣ ᆤ ᆥ ᆦ ᆧ ힰ ힱ ힲ ힳ ힴ ힵ ힶ ힷ ힸ ힹ ힺ ힻ ힼ ힽ ힾ ힿ ퟀ ퟁ ퟂ ퟃ ퟄ ퟅ ퟆ}}
*종성: {{옛한글 인라인|ᆨ ᆩ ᆪ ᆫ ᆬ ᆭ ᆮ ᆯ ᆰ ᆱ ᆲ ᆳ ᆴ ᆵ ᆶ ᆷ ᆸ ᆹ ᆺ ᆻ ᆼ ᆽ ᆾ ᆿ ᇀ ᇁ ᇂ ᇃ ᇄ ᇅ ᇆ ᇇ ᇈ ᇉ ᇊ ᇋ ᇌ ᇍ ᇎ ᇏ ᇐ ᇑ ᇒ ᇓ ᇔ ᇕ ᇖ ᇗ ᇘ ᇙ ᇚ ᇛ ᇜ ᇝ ᇞ ᇟ ᇠ ᇡ ᇢ ᇣ ᇤ ᇥ ᇦ ᇧ ᇨ ᇩ ᇪ ᇫ ᇬ ᇭ ᇮ ᇯ ᇰ ᇱ ᇲ ᇳ ᇴ ᇵ ᇶ ᇷ ᇸ ᇹ ᇺ ᇻ ᇼ ᇽ ᇾ ᇿ ퟋ ퟌ ퟍ ퟎ ퟏ ퟐ ퟑ ퟒ ퟓ ퟔ ퟕ ퟖ ퟗ ퟘ ퟙ ퟚ ퟛ ퟜ ퟝ ퟞ ퟟ ퟠ ퟡ ퟢ ퟣ ퟤ ퟥ ퟦ ퟧ ퟨ ퟩ ퟪ ퟫ ퟬ ퟭ ퟮ ퟯ ퟰ ퟱ ퟲ ퟳ ퟴ ퟵ ퟶ ퟷ ퟸ ퟹ ퟺ ퟻ}}
== 한계 및 문제점 ==
* [[mw:Extension:WikiEditor/ko|2010 위키텍스트 편집기]]에서만 사용 가능하며, [[mw:2017 wikitext editor/ko|2017 위키텍스트 편집기]] 및 [[mw:Help:VisualEditor/User guide/ko|시각편집기]] 등에서 사용할 수 없습니다.
* 편집 도구의 "[[파일:Codemirror 6 icon.svg|20px|class=skin-invert]] '''{{int:codemirror-toggle-label-short}}'''" 버튼으로 활성화되는 [[mw:Help:Extension:CodeMirror/ko|CodeMirror]] 확장기능과 동시에 사용할 수 없습니다.
* 단축키 등의 기능이 브라우저, 미디어위키, 다른 소도구 등 다른 요소와 충돌할 수 있습니다.
* 방점(<code> 〮</code> <code> 〯</code>) 및 중성 채움 문자(<code>ᅠᅠ</code>)는 수동으로 입력해야 합니다. 초성 채움 문자(<code>ᅟᅟ</code>)를 사용해야 하는 경우는 종성을 먼저 입력하면 바로 사용이 가능합니다.
== 구성 ==
* [[미디어위키:Gadget-akinput-core.js]] - [[#원본 라이선스|MIT License]]
* [[미디어위키:Gadget-akinput-mediawiki.js]]
* [[미디어위키:Gadget-akinput.css]]
== 외부 링크 ==
* [https://github.com/bab2min/akorn-input Javascript 기반 웹 브라우저용 옛한글 입력기 akorn-input] - GitHub
== 원본 라이선스 ==
<pre>
MIT License
Copyright (c) 2018
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
</pre>
[[:분류:위키문헌 도움말]]
dii6ejh1wl93plrf2hw3u199j7vviw0
User:DVRTed/AINB-helper.js
2
178129
762112
761960
2026-09-17T17:04:32Z
DVRTed
55993
enwiki sync;
762112
javascript
text/javascript
$(async () => {
// Userscript to help generating tracking subpages at [[WP:AINB]]
/* globals mw, $ */
// <nowiki>
const APP_ID = "ainb-helper";
const APP_AD = "(using [[User:DVRTed/AINB-helper|AINB-helper]])";
const DEBUG_MODE = false;
const DEBUG_PAGE = "User:DVRTed/sandbox2";
const require = mw.loader.require;
await mw.loader.using([
"vue",
"@wikimedia/codex",
"mediawiki.api",
"mediawiki.util",
]);
const api = new mw.Api();
const Vue = require("vue");
let current_app = null;
function close_app() {
if (current_app) {
current_app.unmount();
current_app = null;
}
document.getElementById(APP_ID)?.remove();
}
// reuseable function to create and mount the app
// that registers a bunch of components and handles dups
function create_app(App) {
const { createMwApp } = Vue;
const codex = require("@wikimedia/codex");
close_app();
const mount_point = document.createElement("div");
mount_point.id = APP_ID;
document.body.appendChild(mount_point);
const app = createMwApp({
...App,
mixins: [
{
methods: {
handle_dialog_close() {
close_app();
},
},
},
...(App.mixins || []),
],
});
const {
CdxButton,
CdxCheckbox,
CdxCombobox,
CdxDialog,
CdxField,
CdxMenuButton,
CdxProgressBar,
CdxRadio,
CdxSelect,
CdxTextArea,
CdxTextInput,
} = codex;
Object.entries({
CdxButton,
CdxCheckbox,
CdxCombobox,
CdxDialog,
CdxField,
CdxMenuButton,
CdxProgressBar,
CdxRadio,
CdxSelect,
CdxTextArea,
CdxTextInput,
}).forEach(([name, c]) => app.component(name, c));
app.mount(mount_point);
current_app = app;
}
function create_main_app() {
const { nextTick } = Vue;
create_app({
template: generate_main_template(),
data() {
return {
is_open: true,
step: 1,
username: "",
normalized_username: "",
normalized_usernames: [],
anchor_date: "2022-12-01",
end_date: "",
loading: false,
progress: 0,
edit_count: 0,
error: "",
article_groups: [],
article_search: "",
sort_mode: "recent",
selected_article_title: "",
creating: false,
create_error: "",
generated_wikitext: "",
target_page_title: "",
target_page_url: "",
viewing_diff_edit: null,
filter_menu_selected: null,
available_tags: [],
selected_tags_map: {},
tag_dialog_open: false,
tag_counts: {},
extra_notes: "",
notes_visible: false,
};
},
computed: {
dialog_title() {
if (this.step === 1) return "Generate tracking subpage for AINB";
if (this.step === 2) return "Select diffs to include";
return "Page Created";
},
total_selected_diffs() {
return this.article_groups.reduce(
(sum, group) => sum + group.selected_count,
0
);
},
total_selected() {
return this.article_groups.filter((group) => group.selected_count > 0)
.length;
},
total_groups() {
return this.article_groups.length;
},
all_selected() {
return (
this.article_groups.length > 0 &&
this.article_groups.every((group) => group.all_selected)
);
},
some_selected() {
return this.article_groups.some(
(group) => group.some_selected || group.all_selected
);
},
current_date() {
return new Date().toISOString().split("T")[0];
},
diff_dialog_open: {
get() {
return !!this.viewing_diff_edit;
},
set(val) {
if (!val) this.viewing_diff_edit = null;
},
},
diff_edit_index() {
if (!this.selected_group || !this.viewing_diff_edit) return -1;
return this.selected_group.edits.findIndex(
(edit) => edit.revid === this.viewing_diff_edit.revid
);
},
has_prev_diff() {
return this.diff_edit_index > 0;
},
has_next_diff() {
return (
this.diff_edit_index >= 0 &&
this.selected_group &&
this.diff_edit_index < this.selected_group.edits.length - 1
);
},
filtered_sorted_groups() {
let groups = this.article_groups;
const query = this.article_search.trim().toLowerCase();
if (query) {
groups = groups.filter((g) =>
g.title.toLowerCase().includes(query)
);
}
groups = [...groups];
if (this.sort_mode === "edits") {
groups.sort((a, b) => b.edits.length - a.edits.length);
} else if (this.sort_mode === "alpha") {
groups.sort((a, b) => a.title.localeCompare(b.title));
} else if (this.sort_mode === "recent") {
groups.sort(
(a, b) =>
new Date(b.edits[0].timestamp) - new Date(a.edits[0].timestamp)
);
}
return groups;
},
selected_group() {
return (
this.article_groups.find(
(g) => g.title === this.selected_article_title
) || null
);
},
filter_menu_items() {
return [
{ value: "smaller", label: "Unselect smaller edits" },
{ value: "tag", label: "Unselect edits by tag" },
{ value: "non_creations", label: "Unselect non-creations" },
];
},
selected_tag_list() {
return this.available_tags.filter(
(tag) => this.selected_tags_map[tag]
);
},
tags_in_selection() {
return this.available_tags.filter(
(tag) => (this.tag_counts[tag] || 0) > 0
);
},
is_multiple_users() {
return this.normalized_usernames.length > 1;
},
},
methods: {
fire_hook(selector) {
nextTick(() => {
const $content = $(selector);
if ($content.length) {
mw.hook("wikipage.content").fire($content);
}
});
},
select_article(title) {
this.selected_article_title = title;
this.fire_hook(".ainb-revisions-table");
},
update_group_selection(group) {
const selected = group.edits.filter((edit) => edit.selected).length;
group.selected_count = selected;
group.all_selected = selected === group.edits.length;
group.some_selected = selected > 0 && selected < group.edits.length;
},
toggle_article(group) {
const new_value = !group.all_selected;
group.edits.forEach((edit) => (edit.selected = new_value));
this.update_group_selection(group);
},
toggle_all() {
const new_value = !this.all_selected;
this.article_groups.forEach((group) => {
group.edits.forEach((edit) => (edit.selected = new_value));
this.update_group_selection(group);
});
},
append_filter_note(text) {
const line = `* ${text}`;
this.extra_notes = this.extra_notes
? `${this.extra_notes}\n${line}`
: line;
this.notes_visible = true;
},
unselect_smaller_edits() {
const input = prompt("Unselect edits smaller than (bytes):", "35");
if (input === null) return;
const threshold = parseInt(input, 10);
if (isNaN(threshold)) return;
this.article_groups.forEach((group) => {
group.edits.forEach((edit) => {
if (edit.selected && Math.abs(edit.sizediff) < threshold) {
edit.selected = false;
}
});
this.update_group_selection(group);
});
this.append_filter_note(
`Edits smaller than +/- ${threshold} bytes were excluded.`
);
},
handle_filter_menu_select(value) {
this.filter_menu_selected = null;
if (value === "smaller") {
this.unselect_smaller_edits();
} else if (value === "tag") {
this.open_tag_dialog();
} else if (value === "non_creations") {
this.unselect_non_creations();
}
},
unselect_non_creations() {
this.article_groups.forEach((group) => {
group.edits.forEach((edit) => {
const is_creation = edit.new !== undefined;
if (edit.selected && !is_creation) {
edit.selected = false;
}
});
this.update_group_selection(group);
});
this.append_filter_note("Non-creation edits were excluded.");
},
open_tag_dialog() {
this.selected_tags_map = Object.fromEntries(
this.available_tags.map((tag) => [tag, false])
);
const counts = {};
this.article_groups.forEach((group) => {
group.edits.forEach((edit) => {
if (!edit.selected) return;
(edit.tags || []).forEach((tag) => {
counts[tag] = (counts[tag] || 0) + 1;
});
});
});
this.tag_counts = counts;
this.tag_dialog_open = true;
},
unselect_by_tag() {
const tags_to_unselect = new Set(this.selected_tag_list);
this.article_groups.forEach((group) => {
group.edits.forEach((edit) => {
if (
edit.selected &&
edit.tags?.some((tag) => tags_to_unselect.has(tag))
) {
edit.selected = false;
}
});
this.update_group_selection(group);
});
this.append_filter_note(
`Edits tagged "${[...tags_to_unselect].join(
'", "'
)}" were excluded.`
);
this.tag_dialog_open = false;
},
async fetch_contributions() {
this.loading = true;
this.error = "";
this.progress = 0;
this.extra_notes = "";
this.notes_visible = false;
try {
const edits = [];
let continuation = null;
const raw_users = this.username
.split("|")
.map((u) => u.trim().replace(/^user:/i, ""))
.filter(Boolean);
if (raw_users.length === 0) {
this.error = "Please enter a username.";
return;
}
// check for users w/ too many edits
const user_info = await api.get({
action: "query",
list: "users",
ususers: raw_users.join("|"),
usprop: "editcount",
});
const users = user_info.query?.users || [];
const edit_count = users.reduce(
(sum, u) => sum + (u.editcount || 0),
0
);
if (edit_count > 20000) {
if (
!confirm(
`User has over 20k edits (${edit_count}). Are you sure you want to continue?`
)
) {
this.error = "Manually cancelled: User has too many edits.";
return;
}
} else if (!edit_count) {
this.error =
"No edits found in the timeframe. Note: the username is case-sensitive.";
return;
}
const normalized_users = users
.filter((u) => u.name && !u.missing && !u.invalid)
.map((u) => u.name);
this.normalized_usernames = normalized_users;
this.normalized_username = normalized_users[0] || "";
if (normalized_users.length > 1) {
const user_list = normalized_users
.map((u) => `[[User:${u}]]`)
.join(", ");
this.extra_notes = `* Includes contributions from multiple accounts: ${user_list}`;
this.notes_visible = true;
}
const ucend_timestamp = this.anchor_date
? `${this.anchor_date}T00:00:00Z`
: undefined;
const ucstart_timestamp = this.end_date
? `${this.end_date}T00:00:00Z`
: undefined;
do {
const params = {
action: "query",
list: "usercontribs",
ucnamespace: 0,
ucuser: normalized_users.join("|"),
...(ucend_timestamp ? { ucend: ucend_timestamp } : {}),
...(ucstart_timestamp ? { ucstart: ucstart_timestamp } : {}),
uclimit: "max",
ucprop: "ids|title|timestamp|comment|sizediff|tags|flags|user",
ucdir: "older",
...continuation,
};
const response = await api.get(params);
if (response.error) throw new Error(response.error.info);
edits.push(...response.query.usercontribs);
this.progress = edits.length;
continuation = response.continue;
} while (continuation);
const valid_edits = edits.filter(
(edit) => !edit.tags?.includes("mw-reverted")
);
const groups = {};
valid_edits.forEach((edit) => {
if (!groups[edit.title]) {
groups[edit.title] = {
title: edit.title,
edits: [],
all_selected: false,
some_selected: false,
selected_count: 0,
};
}
groups[edit.title].edits.push({
...edit,
selected: false,
diff_loading: false,
diff_content: "",
});
});
this.edit_count = valid_edits.length;
const tag_set = new Set();
valid_edits.forEach((edit) => {
(edit.tags || []).forEach((tag) => tag_set.add(tag));
});
this.available_tags = Array.from(tag_set).sort();
this.article_groups = Object.values(groups);
this.article_groups.forEach((group) =>
this.update_group_selection(group)
);
if (this.article_groups.length === 0) {
this.error = "No contributions found in the specified period.";
} else {
this.step = 2;
const top_article = this.filtered_sorted_groups[0];
if (top_article) this.select_article(top_article.title);
const page_title = DEBUG_MODE
? DEBUG_PAGE
: `Wikipedia:AI noticeboard/${this.current_date} ${this.normalized_username}`;
this.target_page_title = page_title;
this.target_page_url = mw.util.getUrl(page_title);
}
} catch (error) {
this.error = "Error fetching contributions: " + error.message;
console.error(error);
} finally {
this.loading = false;
}
},
show_diff_popup(edit) {
this.viewing_diff_edit = edit;
this.load_diff(edit);
},
close_diff_popup() {
this.viewing_diff_edit = null;
},
go_to_diff(offset) {
if (!this.selected_group || this.diff_edit_index < 0) return;
const next_edit =
this.selected_group.edits[this.diff_edit_index + offset];
if (next_edit) this.show_diff_popup(next_edit);
},
jump_to_diff(revid) {
if (!this.selected_group) return;
const edit = this.selected_group.edits.find((e) => e.revid == revid);
if (edit) this.show_diff_popup(edit);
},
async load_diff(edit) {
if (edit.diff_content || edit.diff_loading) return;
edit.diff_loading = true;
try {
const response = await api.get({
action: "compare",
fromrev: edit.revid,
torelative: "prev",
prop: "diff",
});
if (response.compare?.["*"]) {
edit.diff_content = `<table class="diff">${response.compare["*"]}</table>`;
} else {
edit.diff_content = "<p>Could not load diff.</p>";
}
} catch (error) {
console.error("Error loading diff:", error);
edit.diff_content =
"<p>Error loading diff: " + error.message + "</p>";
} finally {
edit.diff_loading = false;
}
},
async generate_report() {
const wikitext = this.build_wikitext();
this.generated_wikitext = wikitext;
this.creating = true;
this.create_error = "";
this.step = 3;
try {
await api.postWithEditToken({
action: "edit",
title: this.target_page_title,
text: wikitext,
summary: `Creating tracking subpage ${APP_AD}`,
});
} catch (error) {
this.create_error = "Error creating page: " + error.message;
console.error(error);
} finally {
this.creating = false;
}
},
build_wikitext() {
const selected_groups = this.article_groups
.map((group) => ({
...group,
edits: group.edits.filter((edit) => edit.selected),
}))
.filter((group) => group.edits.length > 0);
let wikitext = `{{NOINDEX|visible=yes}}\nRelevant report and discussion may be viewable on the talk page.\n\n`;
wikitext += `== Tracking list ==\n`;
if (this.extra_notes.trim()) {
wikitext += `{{Notice |heading=Notes |\n${this.extra_notes.trim()}\n}}\n\n`;
}
wikitext += `{{AIC article list|\n`;
selected_groups.forEach((group) => {
const links = group.edits
.map((edit) => {
const edit_size = this.format_bytes(edit.sizediff);
const edit_link = `[[Special:Diff/${edit.revid}|(${edit_size})]]`;
const creation_note =
edit.new !== undefined ? " (page created)" : "";
return `${edit_link}${creation_note}`;
})
.join(" ");
const edit_count = group.edits.length;
const edit_str = edit_count > 1 ? "edits" : "edit";
wikitext += `{{AIC article row|article=${group.title}|status=requested|notes=${edit_count} ${edit_str}: ${links}}}\n`;
});
wikitext += `}}\n`;
return wikitext;
},
async copy_wikitext() {
try {
await navigator.clipboard.writeText(this.build_wikitext());
mw.notify("Wikitext copied to clipboard.", { type: "success" });
} catch (err) {
mw.notify("Failed to copy to clipboard.", { type: "error" });
}
},
get_diff_url(revid) {
return mw.util.getUrl(`Special:Diff/${revid}`);
},
get_article_url(title) {
return mw.util.getUrl(title);
},
get_history_url(title) {
return mw.util.getUrl(title, { action: "history" });
},
get_user_url(username) {
return mw.util.getUrl(`User:${username}`);
},
get_contribs_url(username) {
return mw.util.getUrl(`Special:Contributions/${username}`);
},
get_group_users(group) {
if (!group?.edits) return "";
const users = [
...new Set(group.edits.map((e) => e.user).filter(Boolean)),
];
return users.length ? users.join(", ") : this.normalized_username;
},
format_bytes(bytes) {
return (bytes > 0 ? "+" : "") + (bytes || 0);
},
format_date(timestamp) {
if (!timestamp) return "";
const date = new Date(timestamp);
if (isNaN(date.getTime())) return timestamp;
return date.toLocaleString(undefined, {
year: "numeric",
month: "short",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
});
},
get_size_class(bytes) {
return bytes > 0 ? "ainb-pos" : bytes < 0 ? "ainb-neg" : "ainb-neu";
},
truncate(string, max_length) {
return string?.length > max_length
? string.slice(0, max_length - 1) + "..."
: string || "";
},
},
});
}
function generate_main_template() {
const step1 = `
<div v-if="step === 1" class="ainb-step">
<div v-if="!loading">
<p>Enter the username</p>
<cdx-text-input v-model="username" autocomplete="off" data-bwignore="true" data-lpignore="true" data-1p-ignore
placeholder="User:ExampleUser or ExampleUser" @keydown.enter="fetch_contributions" />
<div class="ainb-date-field">
<label for="ainb-anchor-date">Only fetch edits made after:</label>
<input id="ainb-anchor-date" type="date" v-model="anchor_date" class="ainb-date-input" />
<p class="ainb-date-hint">Defaults to December 2022, the public release date of ChatGPT.</p>
</div>
<div class="ainb-date-field">
<label for="ainb-end-date">Only fetch edits made before:</label>
<input id="ainb-end-date" type="date" v-model="end_date" class="ainb-date-input" />
<p class="ainb-date-hint">Leave blank to fetch up to the most recent edit.</p>
</div>
</div>
<div v-if="error" class="ainb-error">{{ error }}</div>
<div v-if="loading" class="ainb-loading">
<p>Fetching contributions... {{ progress > 0 ? progress + ' found' : '' }}</p>
<cdx-progress-bar inline></cdx-progress-bar>
</div>
</div>
`;
const step2 = `
<div v-if="step === 2" class="ainb-step2">
<div class="ainb-step2-subtitle">
<template v-if="is_multiple_users">Multiple users</template>
<template v-else>
<a :href="get_user_url(normalized_username)" target="_blank">User:{{ normalized_username }}</a>
· <a :href="get_contribs_url(normalized_username)" target="_blank">(contrib)</a>
</template>
· {{ edit_count }} edit(s) across {{ article_groups.length }} article(s)
</div>
<div class="ainb-step2-toolbar">
<cdx-checkbox :model-value="all_selected" :indeterminate="some_selected && !all_selected"
@update:model-value="toggle_all">Select all</cdx-checkbox>
<cdx-menu-button v-model:selected="filter_menu_selected" weight="normal" :menu-items="filter_menu_items"
:disabled="!some_selected" @update:selected="handle_filter_menu_select">Filter selected</cdx-menu-button>
<span class="ainb-total-badge"><b>{{ total_selected }}</b> of {{ total_groups }} articles selected</span>
</div>
<div v-if="notes_visible" class="ainb-notes-field">
<label for="ainb-extra-notes">Notes for tracking page (e.g., applied filters)</label>
<textarea id="ainb-extra-notes" v-model="extra_notes" rows="3"
placeholder="Text to be added above the tracker..."></textarea>
</div>
<cdx-button v-else weight="quiet" class="ainb-add-note-btn" @click="notes_visible = true">+ Add a note</cdx-button>
<div class="ainb-step2-layout">
<div class="ainb-article-list">
<div class="ainb-article-list-controls">
<cdx-text-input v-model="article_search" placeholder="Filter articles..."
class="ainb-article-search"></cdx-text-input>
<div class="ainb-sort-toggle">
<button type="button" :class="{ active: sort_mode === 'edits' }" @click="sort_mode = 'edits'">Most
edits</button>
<button type="button" :class="{ active: sort_mode === 'alpha' }"
@click="sort_mode = 'alpha'">A-Z</button>
<button type="button" :class="{ active: sort_mode === 'recent' }"
@click="sort_mode = 'recent'">Recent</button>
</div>
</div>
<ul class="ainb-article-items">
<li v-for="group in filtered_sorted_groups" :key="group.title" class="ainb-article-item"
:class="{ 'ainb-article-item-active': group.title === selected_article_title, 'ainb-article-item-picked': group.selected_count > 0 }"
@click="select_article(group.title)">
<cdx-checkbox :model-value="group.all_selected"
:indeterminate="group.some_selected && !group.all_selected"
@update:model-value="toggle_article(group)" @click.stop></cdx-checkbox>
<div class="ainb-article-item-info">
<div class="ainb-article-item-title">{{ group.title }}</div>
<div class="ainb-article-item-meta">
<span>{{ group.edits.length }} edit(s)</span>
<span v-if="group.selected_count > 0" class="ainb-article-item-badge">· selected {{
group.selected_count }}/{{ group.edits.length }}</span>
</div>
</div>
</li>
<li v-if="filtered_sorted_groups.length === 0" class="ainb-article-empty">No articles match "{{
article_search }}"</li>
</ul>
</div>
<div class="ainb-revisions-panel">
<template v-if="selected_group">
<div class="ainb-revisions-header">
<div>
<div class="ainb-revisions-title">
<a :href="get_article_url(selected_group.title)" target="_blank">{{ selected_group.title
}}</a>
<a :href="get_history_url(selected_group.title)" target="_blank"
class="ainb-history-link">(hist)</a>
</div>
<div class="ainb-revisions-subtitle">
{{ selected_group.edits.length }} edit(s) by {{ get_group_users(selected_group) }}
</div>
</div>
</div>
<table class="ainb-revisions-table">
<thead>
<tr>
<th class="ainb-col-cb"></th>
<th class="ainb-col-actions">Diff</th>
<th class="ainb-col-time">Date</th>
<th class="ainb-col-size">Size</th>
<th class="ainb-col-summary">Summary</th>
</tr>
</thead>
<tbody>
<tr v-for="edit in selected_group.edits" :key="edit.revid" class="ainb-diff-row"
:class="{ 'ainb-diff-row-selected': edit.selected }">
<td class="ainb-col-cb">
<cdx-checkbox v-model="edit.selected"
@update:model-value="update_group_selection(selected_group)"></cdx-checkbox>
</td>
<td class="ainb-col-actions">
<button type="button" class="ainb-diff-toggle" @click="show_diff_popup(edit)">View
diff</button>
<a :href="get_diff_url(edit.revid)" target="_blank" class="ainb-diff-extlink"
title="Open in new tab">↗</a>
</td>
<td class="ainb-col-time" :title="edit.timestamp">{{ format_date(edit.timestamp) }}</td>
<td :class="['ainb-col-size', get_size_class(edit.sizediff)]">{{ format_bytes(edit.sizediff)
}}</td>
<td class="ainb-col-summary" :title="edit.comment">{{ edit.comment ? truncate(edit.comment,
80) : 'No edit summary' }}</td>
</tr>
</tbody>
</table>
</template>
<div v-else class="ainb-revisions-empty">Select an article on the left to view its revisions.</div>
</div>
</div>
</div>
`;
const diff_dialog = `
<cdx-dialog v-model:open="diff_dialog_open" :title="viewing_diff_edit ? 'Diff for ' + viewing_diff_edit.title : ''"
:use-close-button="true" class="ainb-diff-dialog" @keyup.left="go_to_diff(-1)" @keyup.right="go_to_diff(1)">
<div v-if="viewing_diff_edit" class="ainb-diff-dialog-body">
<div class="ainb-diff-meta">
<select class="ainb-diff-select" :value="viewing_diff_edit.revid"
@change="jump_to_diff($event.target.value)" v-if="selected_group.edits.length > 1">
<option v-for="(e, idx) in selected_group.edits" :key="e.revid" :value="e.revid">
{{ idx + 1 }} / {{ selected_group.edits.length }} — {{ format_date(e.timestamp) }} ({{
format_bytes(e.sizediff) }})
</option>
</select>
<a :href="get_diff_url(viewing_diff_edit.revid)" target="_blank" class="ainb-diff-meta-link">Open in new tab
↗</a>
</div>
<div class="ainb-diff-meta-include">
<cdx-checkbox v-model="viewing_diff_edit.selected"
@update:model-value="update_group_selection(selected_group)">Include</cdx-checkbox>
</div>
<div class="ainb-diff-meta-comment" :title="viewing_diff_edit.comment"><span :class="['ainb-diff-meta-size', get_size_class(viewing_diff_edit.sizediff)]">{{
format_bytes(viewing_diff_edit.sizediff) }} bytes</span> · <span
class="ainb-diff-meta-comment-label">Summary:</span> {{ viewing_diff_edit.comment || 'No edit summary'
}}</div>
<div v-if="viewing_diff_edit.diff_loading" class="ainb-diff-loading">Loading diff...</div>
<div v-else-if="viewing_diff_edit.diff_content" class="ainb-diff-content"
v-html="viewing_diff_edit.diff_content"></div>
<div v-else class="ainb-diff-loading">No content loaded.</div>
</div>
<template #footer>
<div class="ainb-dialog-footer">
<div class="ainb-diff-nav">
<cdx-button @click="go_to_diff(-1)" :disabled="!has_prev_diff">← Prev</cdx-button>
<cdx-button @click="go_to_diff(1)" :disabled="!has_next_diff">Next →</cdx-button>
</div>
<cdx-button @click="close_diff_popup">Close</cdx-button>
</div>
</template>
</cdx-dialog>
`;
const tag_dialog = `
<cdx-dialog v-model:open="tag_dialog_open" title="Unselect edits by tag" :use-close-button="true"
class="ainb-tag-dialog">
<p v-if="tags_in_selection.length === 0">No tags found on the selected edits.</p>
<div v-else>
<cdx-checkbox v-for="tag in tags_in_selection" :key="tag" v-model="selected_tags_map[tag]">
{{ tag }} ({{ tag_counts[tag] }} edit{{ tag_counts[tag] === 1 ? '' : 's' }})
</cdx-checkbox>
</div>
<template #footer>
<div class="ainb-dialog-footer">
<div></div>
<div>
<cdx-button @click="tag_dialog_open = false">Cancel</cdx-button>
<cdx-button action="progressive" weight="primary" @click="unselect_by_tag"
:disabled="selected_tag_list.length === 0">
Unselect
</cdx-button>
</div>
</div>
</template>
</cdx-dialog>
`;
const step3 = `
<div v-if="step === 3" class="ainb-step">
<div v-if="creating" class="ainb-loading">
<p>Creating page...</p>
<cdx-progress-bar inline></cdx-progress-bar>
</div>
<div v-else-if="create_error" class="ainb-error">{{ create_error }}</div>
<div v-else>
<p>Page created successfully!</p>
<p><a :href="target_page_url" target="_blank">{{ target_page_title }}</a></p>
</div>
</div>
`;
const footer = `
<template #footer>
<div class="ainb-dialog-footer">
<div v-if="step === 1"></div>
<cdx-button v-if="step === 1" action="progressive" weight="primary" @click="fetch_contributions"
:disabled="loading || !username">
{{ loading ? 'Fetching...' : 'Fetch contributions' }}</cdx-button>
<template v-if="step === 2">
<div class="ainb-subpage-info">Target: <strong>{{ target_page_title }}</strong></div>
<div class="ainb-footer-buttons">
<cdx-button @click="step = 1">Back</cdx-button>
<cdx-button @click="copy_wikitext" :disabled="total_selected_diffs === 0">Copy wikitext
</cdx-button>
<cdx-button action="progressive" weight="primary" @click="generate_report"
:disabled="total_selected_diffs === 0">Create Page
</cdx-button>
</div>
</template>
<template v-if="step === 3">
<div></div>
<div>
<cdx-button @click="handle_dialog_close">Close</cdx-button>
</div>
</template>
</div>
</template>
`;
return `
<div>
<cdx-dialog class="ainb-helper" v-model:open="is_open"
:title="dialog_title" :use-close-button="true"
@update:open="handle_dialog_close">
${step1}
${step2}
${step3}
${footer}
</cdx-dialog>
${diff_dialog}
${tag_dialog}
</div>
`;
}
function get_article_row_regex(article, global = false) {
const escaped_article = mw.util.escapeRegExp(article);
return new RegExp(
`\\{\\{AIC article row\\s*\\|\\s*(?:article=)?\\s*${escaped_article}\\s*(?:\\|\\s*(?:status=)?\\s*([^|}]*))?(?:\\s*\\|\\s*(?:notes=)?\\s*([^}]*))?\\s*\\}\\}`,
global ? "ig" : "i"
);
}
function create_edit_table_app(articles_input) {
const articles = Array.isArray(articles_input)
? articles_input
: [articles_input];
create_app({
template: generate_edit_table_template(),
data() {
return {
is_open: true,
articles,
rows: [],
original_rows: [],
loading: false,
saving: false,
error: "",
wikitext: "",
status_options: [
{ value: "completed", label: "Completed", aliases: ["c"] },
{ value: "ongoing", label: "Ongoing", aliases: ["o"] },
{
value: "unnecessary",
label: "Unnecessary",
aliases: ["u", "unneeded"],
},
{
value: "requested",
label: "Requested/To-do",
aliases: ["r", "td", "todo", "to do", "t"],
},
],
};
},
computed: {
is_single() {
return this.articles.length === 1;
},
dialog_title() {
return this.is_single ? "Editing row" : "Batch edit";
},
dialog_class() {
return this.is_single ? "ainb-edit-table" : "ainb-batch-edit-table";
},
duplicate_error() {
const link = `<a href="${mw.util.getUrl(
"User:DVRTed/AINB-helper#Known_issues"
)}" target="_blank" rel="noopener noreferrer">User:DVRTed/AINB-helper#Known_issues</a>`;
return `This entry is duplicated, so it cannot be edited with the script; see ${link}.`;
},
can_save() {
if (this.saving || this.loading || this.rows.length === 0)
return false;
return this.rows.some(
(row) => !row.multiple_matches && Boolean(row.status)
);
},
},
methods: {
get_article_url(title) {
return mw.util.getUrl(title);
},
normalize_status(value) {
const trimmed = value?.trim().toLowerCase() || "";
const status = this.status_options.find(
(option) =>
option.value === trimmed || option.aliases?.includes(trimmed)
);
return status ? status.value : "requested";
},
async load_row_data() {
this.loading = true;
this.error = "";
try {
const page_name = mw.config.get("wgPageName");
const result = await api.get({
action: "parse",
page: page_name,
prop: "wikitext",
});
const wikitext = result.parse.wikitext["*"];
this.wikitext = wikitext;
const rows = [];
for (const article of this.articles) {
const global_matches = [
...wikitext.matchAll(get_article_row_regex(article, true)),
];
if (global_matches.length > 0) {
const match = global_matches[0];
rows.push({
article,
status: this.normalize_status(match[1]?.trim()),
notes: match[2]?.trim() || "",
multiple_matches: global_matches.length > 1,
});
}
}
if (rows.length === 0) {
this.error = "Could not find row data";
} else {
this.rows = rows;
this.original_rows = structuredClone(rows);
if (this.is_single && rows[0].multiple_matches) {
this.error = this.duplicate_error;
}
}
} catch (e) {
this.error = "Error loading row data: " + e.message;
console.error(e);
} finally {
this.loading = false;
}
},
async save_changes() {
this.saving = true;
this.error = "";
try {
const page_name = mw.config.get("wgPageName");
let new_wikitext = this.wikitext;
for (const row of this.rows) {
if (!row.multiple_matches) {
const new_row = `{{AIC article row|article=${
row.article
}|status=${row.status}|notes=${row.notes || ""}}}`;
new_wikitext = new_wikitext.replace(
get_article_row_regex(row.article),
new_row
);
}
}
const changed_rows = this.original_rows.filter((row) => {
const current_row = this.rows.find(
(e) => e.article === row.article
);
if (!current_row || row.multiple_matches) return false;
return (
row.status !== current_row.status ||
(row.notes || "") !== (current_row.notes || "")
);
});
const summary =
this.rows.length === 1
? `Updated row for [[${this.rows[0].article}]] ${APP_AD}`
: `Batch edited ${changed_rows.length} ${
changed_rows.length === 1 ? "row" : "rows"
} ${APP_AD}`;
await api.postWithEditToken({
action: "edit",
title: page_name,
text: new_wikitext,
summary,
});
location.reload();
this.handle_dialog_close();
} catch (e) {
this.error = "Error saving changes: " + e.message;
console.error(e);
} finally {
this.saving = false;
}
},
},
async mounted() {
await this.load_row_data();
},
});
}
function generate_edit_table_template() {
return `
<div>
<cdx-dialog :class="dialog_class" v-model:open="is_open"
:title="dialog_title" :use-close-button="true"
@update:open="handle_dialog_close">
<div v-if="loading" class="ainb-loading">
<p>Loading row data...</p>
<cdx-progress-bar inline></cdx-progress-bar>
</div>
<div v-else-if="error" class="ainb-error" v-html="error"></div>
<div v-else-if="is_single && rows.length === 1" class="ainb-edit-step">
<div class="ainb-form-field">
Article: <strong><a :href="get_article_url(rows[0].article)" target="_blank" rel="noopener noreferrer">{{ rows[0].article }}</a></strong>
</div>
<div class="ainb-form-field">
<div class="ainb-form-label">Status:</div>
<div><cdx-select v-model:selected="rows[0].status" :menu-items="status_options" :disabled="saving"></cdx-select></div>
</div>
<div class="ainb-form-field">
<div class="ainb-form-label">Notes:</div>
<cdx-text-area v-model="rows[0].notes" rows="4" :disabled="saving"></cdx-text-area>
</div>
</div>
<table v-else class="ainb-batch-edit-table-grid">
<thead>
<tr>
<th>Article</th>
<th>Status</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr v-for="row in rows" :key="row.article">
<td>
<a :href="get_article_url(row.article)" target="_blank" rel="noopener noreferrer">
{{ row.article }}
</a>
</td>
<template v-if="row.multiple_matches">
<td colspan="2" class="ainb-error" v-html="duplicate_error"></td>
</template>
<template v-else>
<td>
<cdx-select v-model:selected="row.status" :menu-items="status_options" :disabled="saving"></cdx-select>
</td>
<td>
<cdx-text-area v-model="row.notes" rows="2" :disabled="saving"></cdx-text-area>
</td>
</template>
</tr>
</tbody>
</table>
<template #footer>
<div class="ainb-dialog-footer">
<div></div>
<div>
<cdx-button @click="handle_dialog_close" :disabled="saving">Cancel</cdx-button>
<cdx-button action="progressive" weight="primary"
@click="save_changes" :disabled="!can_save">
{{ saving ? 'Saving...' : 'Save' }}
</cdx-button>
</div>
</div>
</template>
</cdx-dialog>
</div>
`;
}
function create_llm_tag_prod_app() {
const subpage_options = [];
const LAST_THREAD_KEY = "ainb-llm-tag-last-thread";
const LAST_THREAD_TTL_MS = 3 * 60 * 60 * 1000;
create_app({
template: generate_llm_tag_prod_template(),
data() {
return {
is_open: true,
step: 1,
selected_option: "llm_prod",
subpage: "",
subpage_options: subpage_options,
editable_wikitext: "",
editable_summary: "",
saving: false,
save_error: "",
step1_error: "",
checking_page: false,
show_preview: false,
preview_html: "",
preview_loading: false,
};
},
computed: {
filtered_subpage_options() {
const query = (this.subpage || "").trim().toLowerCase();
if (!query) {
return this.subpage_options;
}
return this.subpage_options.filter((item) =>
item.value.toLowerCase().includes(query)
);
},
},
methods: {
async go_to_step2() {
let raw_subpage = this.subpage.trim();
this.step1_error = "";
if (raw_subpage) {
this.checking_page = true;
const [page_title, ...section_parts] = raw_subpage.split("#");
const page = page_title.trim();
const section = section_parts.join("#").trim();
try {
const res = await api.get({
action: "parse",
page: page,
prop: "sections",
redirects: true,
});
if (section) {
const sections = res.parse?.sections || [];
const section_exists = sections.some(
(s) =>
s.line === section ||
s.anchor === section ||
s.line.replace(/_/g, " ") === section.replace(/_/g, " ")
);
if (!section_exists) {
this.step1_error = `Section "${section}" does not exist on "${page}"`;
return;
}
}
} catch (err) {
this.step1_error = `Page does not exist: "${err}"`;
return;
} finally {
this.checking_page = false;
}
}
let target_link = raw_subpage;
mw.storage.setObject(LAST_THREAD_KEY, {
subpage: raw_subpage,
selected_option: this.selected_option,
ts: Date.now(),
});
const see_clause = target_link ? `, see [[${target_link}]]` : "";
const ai_reason = target_link ? ` |reason= [[${target_link}]]` : "";
if (this.selected_option === "llm_prod") {
this.editable_wikitext = `{{subst:Prod llm\n|reason=[[WP:LLMPRV|Presumptive removal of LLM-generated content]]${see_clause}. Feel free to reinstate by following [[WP:LLMPRVOBJ|the procedures for disputing presumptive removal of LLM-generated content]].}}`;
this.editable_summary = `[[WP:LLMPRV|Presumptive removal of LLM-generated content]]${see_clause}. Feel free to reinstate by following [[WP:LLMPRVOBJ|the procedures for disputing presumptive removal of LLM-generated content]].`;
} else {
this.editable_wikitext = `{{AI-generated${ai_reason} |{{subst:DATE}}}}`;
this.editable_summary = `Added AI tag${see_clause}`;
}
this.show_preview = false;
this.step = 2;
},
go_back_to_step1() {
mw.storage.remove(LAST_THREAD_KEY);
this.step1_error = "";
this.step = 1;
},
async toggle_preview() {
if (this.show_preview) {
this.show_preview = false;
return;
}
this.preview_loading = true;
this.show_preview = true;
try {
const res = await api.post({
action: "parse",
text: this.editable_wikitext,
title: mw.config.get("wgPageName"),
pst: true,
prop: "text",
});
if (res.parse?.text?.["*"]) {
this.preview_html = res.parse.text["*"];
} else {
this.preview_html = "Could not generate preview.";
}
} catch (err) {
console.error("Preview error:", err);
this.preview_html = `Preview error: ${err.message}`;
} finally {
this.preview_loading = false;
}
},
async save_edit() {
this.saving = true;
this.save_error = "";
try {
const page_name = mw.config.get("wgPageName");
const prepended_text = this.editable_wikitext.trim() + "\n";
const edit_summary = `${this.editable_summary.trim()} ${APP_AD}`;
await api.postWithEditToken({
action: "edit",
title: page_name,
prependtext: prepended_text,
summary: edit_summary,
});
mw.notify("Edit submitted successfully!", { type: "success" });
location.reload();
this.handle_dialog_close();
} catch (e) {
this.save_error = "Error submitting edit: " + e;
console.error(e);
} finally {
this.saving = false;
}
},
async fetch_ainb_suggestions() {
const suggestions = [];
try {
const parse_res = await api.get({
action: "parse",
page: "Wikipedia:AI noticeboard",
prop: "sections",
redirects: true,
});
if (parse_res.parse?.sections) {
parse_res.parse.sections.forEach((section) => {
suggestions.push(`Wikipedia:AI noticeboard#${section.line}`);
});
}
const subpages_res = await api.get({
action: "query",
list: "prefixsearch",
pssearch: "Wikipedia:AI noticeboard/",
pslimit: 100,
});
if (subpages_res.query?.prefixsearch) {
subpages_res.query.prefixsearch.forEach((item) => {
suggestions.push(item.title);
});
}
} catch (err) {
console.error("Error fetching AINB suggestions:", err);
}
return suggestions;
},
},
mounted() {
const saved = mw.storage.getObject(LAST_THREAD_KEY);
if (
saved &&
saved.subpage &&
Date.now() - saved.ts < LAST_THREAD_TTL_MS
) {
this.subpage = saved.subpage;
this.selected_option = saved.selected_option || this.selected_option;
this.go_to_step2();
}
this.fetch_ainb_suggestions().then((suggestions) => {
if (suggestions.length > 0) {
this.subpage_options = suggestions.map((sp) => ({
value: sp,
label: sp,
}));
}
});
},
});
}
function generate_llm_tag_prod_template() {
return `
<div>
<cdx-dialog class="ainb-llm-dialog" v-model:open="is_open"
title="LLM tag / prod" :use-close-button="true"
@update:open="handle_dialog_close">
<div v-if="step === 1">
<div v-if="step1_error" class="ainb-error">{{ step1_error }}</div>
<cdx-field>
<cdx-radio v-model="selected_option" input-value="llm_prod" :inline="true" :disabled="checking_page">
Prod LLM
</cdx-radio>
<cdx-radio v-model="selected_option" input-value="ai_tag" :inline="true" :disabled="checking_page">
Add {{AI-generated}} tag
</cdx-radio>
</cdx-field>
<cdx-field>
<template #description>Tip: Type the username to autocomplete from Wikipedia:AI noticeboard. You can leave this blank to proceed anyway.</template>
<cdx-combobox v-model:selected="subpage" :menu-items="filtered_subpage_options" placeholder="Relevant thread or subpage (optional)" :disabled="checking_page"></cdx-combobox>
</cdx-field>
</div>
<div v-if="step === 2">
<div class="ainb-thread-context">
<span>Thread: <strong>{{ subpage }}</strong></span>
<a href="#" @click.prevent="go_back_to_step1">Change</a>
</div>
<div v-if="save_error" class="ainb-error">{{ save_error }}</div>
<cdx-field>
<template #label>Resulting wikitext:</template>
<cdx-text-area v-model="editable_wikitext" rows="5" :disabled="saving"></cdx-text-area>
</cdx-field>
<div class="ainb-preview-link-wrap">
<a href="#" @click.prevent="toggle_preview">
{{ show_preview ? 'Hide preview' : 'Show preview' }}
</a>
</div>
<div v-if="show_preview" class="ainb-preview-box">
<div v-if="preview_loading" class="ainb-loading">Loading preview...</div>
<div v-else class="ainb-preview-content" v-html="preview_html"></div>
</div>
<cdx-field>
<template #label>Edit summary:</template>
<cdx-text-input v-model="editable_summary" :disabled="saving" />
</cdx-field>
</div>
<template #footer>
<div class="ainb-dialog-footer">
<div v-if="step === 1">
<cdx-button @click="handle_dialog_close">Cancel</cdx-button>
</div>
<div v-if="step === 1">
<cdx-button action="progressive" weight="primary" @click="go_to_step2" :disabled="checking_page">
{{ checking_page ? 'Checking...' : 'Next' }}
</cdx-button>
</div>
<div v-if="step === 2">
<cdx-button @click="go_back_to_step1" :disabled="saving">Back</cdx-button>
</div>
<div v-if="step === 2">
<cdx-button action="progressive" weight="primary" @click="save_edit" :disabled="saving || !editable_wikitext">
{{ saving ? 'Saving...' : 'Submit edit' }}
</cdx-button>
</div>
</div>
</template>
</cdx-dialog>
</div>
`;
}
const CATEGORY_PAGE_NAME = "Category:AI_noticeboard_open_cleanup_cases";
const CATEGORY_STATS_PAGE = "User:DVRTed bot/AINB-stats.json";
function init_category_stats_app() {
if (mw.config.get("wgPageName") !== CATEGORY_PAGE_NAME) return;
const $target = $("#mw-content-text").first();
if (!$target.length) return;
const $wrap = $(`
<div class="ainb-category-stats ainb-progress-wrap">
<div class="ainb-progress-top">
<span class="ainb-progress-percent">...</span>
<div class="ainb-progress-top-text">
<div class="ainb-progress-title">AI noticeboard cleanup</div>
<div class="ainb-progress-stats">Loading...</div>
</div>
</div>
<div class="ainb-progress-bar"></div>
<div class="ainb-progress-legend"></div>
<div class="ainb-category-mini"></div>
<div class="ainb-category-meta"><span>Last updated: </span><span>Generated by <a href="${mw.util.getUrl(
"User:DVRTed/AINB-helper"
)}">AINB-helper</a></span></div>
</div>
`);
$target.prepend($wrap);
api
.get({
action: "query",
prop: "revisions",
titles: CATEGORY_STATS_PAGE,
rvslots: "main",
rvprop: "timestamp|content",
format: "json",
formatversion: "2",
})
.then((result) => {
const rev = result.query.pages[0].revisions[0];
const {
active_cases,
total_todo,
total_in_progress,
total_completed,
total_unnecessary,
} = JSON.parse(rev.slots.main.content);
const total_pages =
total_todo + total_in_progress + total_completed + total_unnecessary;
const resolved = total_completed + total_unnecessary;
const pct = Math.round((resolved / total_pages) * 100);
$wrap
.find(".ainb-category-meta span")
.first()
.text(
`Last updated: ${new Date(rev.timestamp).toLocaleString([], {
month: "short",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "2-digit",
timeZone: "UTC",
timeZoneName: "short",
})}`
);
const items = [
{ key: "todo", count: total_todo },
{ key: "completed", count: total_completed },
{ key: "unnecessary", count: total_unnecessary },
{ key: "ongoing", count: total_in_progress },
].filter(({ count }) => count > 0);
const segments = items
.map(
({ key, count }) =>
`<div class="ainb-seg ainb-seg-${key}" style="width:${
(count / total_pages) * 100
}%" title="${key}: ${count.toLocaleString()}"></div>`
)
.join("");
const legend = items
.map(
({ key, count }) =>
`<span><i class="ainb-dot ainb-seg-${key}"></i>${key} (${count.toLocaleString()})</span>`
)
.join("");
$wrap.find(".ainb-progress-bar").html(segments);
$wrap.find(".ainb-progress-percent").text(`${pct}%`);
$wrap
.find(".ainb-progress-stats")
.text(
`${resolved.toLocaleString()} / ${total_pages.toLocaleString()} resolved`
);
$wrap.find(".ainb-progress-legend").html(legend);
$wrap
.find(".ainb-category-mini")
.html(
`There are <strong>${active_cases.toLocaleString()}</strong> active cases with <strong>${total_todo.toLocaleString()}</strong> pages marked as to-do, ` +
`<strong>${total_in_progress.toLocaleString()}</strong> in progress, <strong>${total_completed.toLocaleString()}</strong> done, ` +
`and <strong>${total_unnecessary.toLocaleString()}</strong> unnecessary.`
);
})
.catch(() => {
$wrap.find(".ainb-progress-stats").text("Could not load AINB stats");
});
}
init_category_stats_app();
// for nicely formatted CSS, see [[User:DVRTed/AINB-helper.css]]
mw.loader.load(
"//en.wikipedia.org/w/index.php?title=User:DVRTed/AINB-helper.css&action=raw&ctype=text/css",
"text/css"
);
// workaround to fix flash of unstyled content on progress bar
mw.util.addCSS(`
.ainb-progress-wrap { margin-bottom: 1em; padding: 8px 12px; border: 1px solid var(--border-color-base, #a2a9b1); border-radius: 4px; }
.ainb-progress-top { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.ainb-progress-percent { font-size: 1.8em; font-weight: 700; line-height: 1; color: var(--color-base, #202122); }
.ainb-progress-top-text { display: flex; flex-direction: column; }
.ainb-progress-title { font-weight: 600; font-size: 0.9em; }
.ainb-progress-stats { font-size: 0.85em; color: var(--color-subtle, #54595d); }
.ainb-progress-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: #eaecf0; }
.ainb-seg { height: 100%; }
.ainb-seg-completed { background: var(--background-color-success, #14866d); }
.ainb-seg-unnecessary, .ainb-seg-unknown { background: var(--background-color-disabled, #c8ccd1); }
.ainb-seg-ongoing { background: var(--background-color-progressive, #36c); }
.ainb-seg-todo { background: var(--background-color-notice, #fc3); }
.ainb-progress-legend { display: flex; gap: 10px; margin-top: 6px; font-size: 0.8em; color: var(--color-subtle, #54595d); text-transform: capitalize; }
.ainb-progress-legend i.ainb-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 3px; }
.ainb-progress-credit { font-size: 0.75em; color: var(--color-subtle, #54595d); font-weight: normal; text-align: right; }
.ainb-progress-hide-row { margin-top: 6px; font-size: 0.85em; }
.ainb-hide-resolved .ainb-row-resolved { display: none; }
`);
function init_row_editing() {
$("table")
.has('tr[class*="aic-row-"]')
.each(function () {
const $table = $(this);
const $thead = $table.find("thead");
$thead.find("tr").prepend('<th class="ainb-action-header">Action</th>');
// batch edit button; populate array of article names.
const articles = $table
.find('tr[class*="aic-row-"]')
.map(function () {
return $(this).find("a").first().text().trim();
})
.get()
.filter(Boolean);
if (articles.length) {
const $button = $(
'<button type="button" class="cdx-button cdx-button--action-progressive">'
)
.text("Batch edit")
.on("click", (e) => {
e.preventDefault();
create_edit_table_app(articles);
});
$table.before($button);
}
// single-row edit buttons
$table.find('tr[class*="aic-row-"]').each(function () {
const $row = $(this);
const $first_cell = $row.find("td").first();
const $link = $first_cell.find("a").first();
if (!$link.length) return;
const $edit_td = $("<td>").addClass("ainb-action-cell");
$first_cell.before($edit_td);
const $edit_button = $("<button>")
.addClass("ainb-edit-btn")
.text("✎")
.attr("title", "Edit this row")
.on("click", (e) => {
e.preventDefault();
create_edit_table_app($link.text().trim());
});
$edit_td.append($edit_button);
});
});
}
function get_row_status($row) {
const match = $row.attr("class")?.match(/\baic-row-(\S+)/);
return match ? match[1] : "unknown";
}
function init_progress_bar() {
const STATUS_KEYS = [
"completed",
"unnecessary",
"ongoing",
"todo",
"unknown",
];
$("table")
.has('tr[class*="aic-row-"]')
.each(function () {
const $table = $(this);
const stats = Object.fromEntries(STATUS_KEYS.map((k) => [k, 0]));
const $rows = $table.find('tr[class*="aic-row-"]');
$rows.each(function () {
const status = get_row_status($(this));
const key = status in stats ? status : "unknown";
stats[key]++;
if (key === "completed" || key === "unnecessary") {
$(this).addClass("ainb-row-resolved");
}
});
const total = Object.values(stats).reduce((a, b) => a + b, 0);
if (!total) return;
const resolved = stats.completed + stats.unnecessary;
const percent = Math.round((resolved / total) * 100);
const active = STATUS_KEYS.filter((key) => stats[key] > 0);
const segments = active
.map(
(key) =>
`<div class="ainb-seg ainb-seg-${key}" style="width:${
(stats[key] / total) * 100
}%" title="${stats[key]} ${key}"></div>`
)
.join("");
const legend = active
.map(
(key) =>
`<span><i class="ainb-dot ainb-seg-${key}"></i>${key} (${stats[key]})</span>`
)
.join("");
const $bar = $(`
<div class="ainb-progress-wrap">
<div class="ainb-progress-top">
<span class="ainb-progress-percent">${percent}%</span>
<div class="ainb-progress-top-text">
<div class="ainb-progress-title">Progress</div>
<div class="ainb-progress-stats">${resolved} / ${total} resolved</div>
</div>
</div>
<div class="ainb-progress-bar">${segments}</div>
<div class="ainb-progress-legend">${legend}</div>
<div class="ainb-progress-credit">Generated by <a href="${mw.util.getUrl(
"User:DVRTed/AINB-helper"
)}">AINB-helper</a></div>
<div class="ainb-progress-hide-row">
<label><input type="checkbox" class="ainb-hide-resolved-cb"> Hide resolved entries</label>
</div>
</div>
`);
$bar.find(".ainb-hide-resolved-cb").on("change", function () {
$table.toggleClass("ainb-hide-resolved", $(this).is(":checked"));
});
$table.before($bar);
});
}
const portlet_link = mw.util.addPortletLink(
"p-tb",
"#",
"New AINB tracking",
"t-ainb-tracking",
"Generate tracking subpage for AINB"
);
$(portlet_link).on("click", function (e) {
e.preventDefault();
create_main_app();
});
const wgPageName = mw.config.get("wgPageName");
// if we're on an AINB tracking subpage, or the debug page,
// enable editing rows
if (
wgPageName.startsWith("Wikipedia:AI_noticeboard/") ||
wgPageName === DEBUG_PAGE
) {
init_progress_bar();
init_row_editing();
}
if ([0, 118].includes(mw.config.get("wgNamespaceNumber"))) {
const llm_portlet_link = mw.util.addPortletLink(
"p-cactions",
"#",
"LLM tag/prod",
"t-llm-tag-prod",
"LLM tag/prod helper"
);
$(llm_portlet_link).on("click", function (e) {
e.preventDefault();
create_llm_tag_prod_app();
});
}
});
// </nowiki>
aydng7o5dz91u493r8tozt70v0r33vh
762113
762112
2026-09-17T17:06:01Z
DVRTed
55993
test https://minify-js.com/
762113
javascript
text/javascript
$(async()=>{const e="ainb-helper",t="(using [[User:DVRTed/AINB-helper|AINB-helper]])",i="User:DVRTed/sandbox2",n=mw.loader.require;await mw.loader.using(["vue","@wikimedia/codex","mediawiki.api","mediawiki.util"]);const s=new mw.Api,a=n("vue");let o=null;function close_app(){o&&(o.unmount(),o=null),document.getElementById(e)?.remove()}function create_app(t){const{createMwApp:i}=a,s=n("@wikimedia/codex");close_app();const r=document.createElement("div");r.id=e,document.body.appendChild(r);const l=i({...t,mixins:[{methods:{handle_dialog_close(){close_app()}}},...t.mixins||[]]}),{CdxButton:d,CdxCheckbox:c,CdxCombobox:p,CdxDialog:g,CdxField:_,CdxMenuButton:u,CdxProgressBar:h,CdxRadio:f,CdxSelect:b,CdxTextArea:v,CdxTextInput:m}=s;Object.entries({CdxButton:d,CdxCheckbox:c,CdxCombobox:p,CdxDialog:g,CdxField:_,CdxMenuButton:u,CdxProgressBar:h,CdxRadio:f,CdxSelect:b,CdxTextArea:v,CdxTextInput:m}).forEach(([e,t])=>l.component(e,t)),l.mount(r),o=l}function get_article_row_regex(e,t=!1){const i=mw.util.escapeRegExp(e);return new RegExp(`\\{\\{AIC article row\\s*\\|\\s*(?:article=)?\\s*${i}\\s*(?:\\|\\s*(?:status=)?\\s*([^|}]*))?(?:\\s*\\|\\s*(?:notes=)?\\s*([^}]*))?\\s*\\}\\}`,t?"ig":"i")}function create_edit_table_app(e){const i=Array.isArray(e)?e:[e];create_app({template:'\n<div>\n <cdx-dialog :class="dialog_class" v-model:open="is_open" \n :title="dialog_title" :use-close-button="true"\n @update:open="handle_dialog_close">\n \n <div v-if="loading" class="ainb-loading">\n <p>Loading row data...</p>\n <cdx-progress-bar inline></cdx-progress-bar>\n </div>\n \n <div v-else-if="error" class="ainb-error" v-html="error"></div>\n \n <div v-else-if="is_single && rows.length === 1" class="ainb-edit-step">\n <div class="ainb-form-field">\n Article: <strong><a :href="get_article_url(rows[0].article)" target="_blank" rel="noopener noreferrer">{{ rows[0].article }}</a></strong>\n </div>\n \n <div class="ainb-form-field">\n <div class="ainb-form-label">Status:</div>\n <div><cdx-select v-model:selected="rows[0].status" :menu-items="status_options" :disabled="saving"></cdx-select></div>\n </div>\n \n <div class="ainb-form-field">\n <div class="ainb-form-label">Notes:</div>\n <cdx-text-area v-model="rows[0].notes" rows="4" :disabled="saving"></cdx-text-area>\n </div>\n </div>\n \n <table v-else class="ainb-batch-edit-table-grid">\n <thead>\n <tr>\n <th>Article</th>\n <th>Status</th>\n <th>Notes</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for="row in rows" :key="row.article">\n <td>\n <a :href="get_article_url(row.article)" target="_blank" rel="noopener noreferrer">\n {{ row.article }}\n </a>\n </td>\n <template v-if="row.multiple_matches">\n <td colspan="2" class="ainb-error" v-html="duplicate_error"></td>\n </template>\n <template v-else>\n <td>\n <cdx-select v-model:selected="row.status" :menu-items="status_options" :disabled="saving"></cdx-select>\n </td>\n <td>\n <cdx-text-area v-model="row.notes" rows="2" :disabled="saving"></cdx-text-area>\n </td>\n </template>\n </tr>\n </tbody>\n </table>\n\n <template #footer>\n <div class="ainb-dialog-footer">\n <div></div>\n <div>\n <cdx-button @click="handle_dialog_close" :disabled="saving">Cancel</cdx-button>\n <cdx-button action="progressive" weight="primary" \n @click="save_changes" :disabled="!can_save">\n {{ saving ? \'Saving...\' : \'Save\' }}\n </cdx-button>\n </div>\n </div>\n </template>\n </cdx-dialog>\n</div>\n ',data:()=>({is_open:!0,articles:i,rows:[],original_rows:[],loading:!1,saving:!1,error:"",wikitext:"",status_options:[{value:"completed",label:"Completed",aliases:["c"]},{value:"ongoing",label:"Ongoing",aliases:["o"]},{value:"unnecessary",label:"Unnecessary",aliases:["u","unneeded"]},{value:"requested",label:"Requested/To-do",aliases:["r","td","todo","to do","t"]}]}),computed:{is_single(){return 1===this.articles.length},dialog_title(){return this.is_single?"Editing row":"Batch edit"},dialog_class(){return this.is_single?"ainb-edit-table":"ainb-batch-edit-table"},duplicate_error:()=>`This entry is duplicated, so it cannot be edited with the script; see ${`<a href="${mw.util.getUrl("User:DVRTed/AINB-helper#Known_issues")}" target="_blank" rel="noopener noreferrer">User:DVRTed/AINB-helper#Known_issues</a>`}.`,can_save(){return!this.saving&&!this.loading&&0!==this.rows.length&&this.rows.some(e=>!e.multiple_matches&&Boolean(e.status))}},methods:{get_article_url:e=>mw.util.getUrl(e),normalize_status(e){const t=e?.trim().toLowerCase()||"",i=this.status_options.find(e=>e.value===t||e.aliases?.includes(t));return i?i.value:"requested"},async load_row_data(){this.loading=!0,this.error="";try{const e=mw.config.get("wgPageName"),t=(await s.get({action:"parse",page:e,prop:"wikitext"})).parse.wikitext["*"];this.wikitext=t;const i=[];for(const e of this.articles){const n=[...t.matchAll(get_article_row_regex(e,!0))];if(n.length>0){const t=n[0];i.push({article:e,status:this.normalize_status(t[1]?.trim()),notes:t[2]?.trim()||"",multiple_matches:n.length>1})}}0===i.length?this.error="Could not find row data":(this.rows=i,this.original_rows=structuredClone(i),this.is_single&&i[0].multiple_matches&&(this.error=this.duplicate_error))}catch(e){this.error="Error loading row data: "+e.message,console.error(e)}finally{this.loading=!1}},async save_changes(){this.saving=!0,this.error="";try{const e=mw.config.get("wgPageName");let i=this.wikitext;for(const e of this.rows)if(!e.multiple_matches){const t=`{{AIC article row|article=${e.article}|status=${e.status}|notes=${e.notes||""}}}`;i=i.replace(get_article_row_regex(e.article),t)}const n=this.original_rows.filter(e=>{const t=this.rows.find(t=>t.article===e.article);return!(!t||e.multiple_matches)&&(e.status!==t.status||(e.notes||"")!==(t.notes||""))}),a=1===this.rows.length?`Updated row for [[${this.rows[0].article}]] ${t}`:`Batch edited ${n.length} ${1===n.length?"row":"rows"} ${t}`;await s.postWithEditToken({action:"edit",title:e,text:i,summary:a}),location.reload(),this.handle_dialog_close()}catch(e){this.error="Error saving changes: "+e.message,console.error(e)}finally{this.saving=!1}}},async mounted(){await this.load_row_data()}})}!function init_category_stats_app(){if("Category:AI_noticeboard_open_cleanup_cases"!==mw.config.get("wgPageName"))return;const e=$("#mw-content-text").first();if(!e.length)return;const t=$(`\n <div class="ainb-category-stats ainb-progress-wrap">\n <div class="ainb-progress-top">\n <span class="ainb-progress-percent">...</span>\n <div class="ainb-progress-top-text">\n <div class="ainb-progress-title">AI noticeboard cleanup</div>\n <div class="ainb-progress-stats">Loading...</div>\n </div>\n </div>\n <div class="ainb-progress-bar"></div>\n <div class="ainb-progress-legend"></div>\n <div class="ainb-category-mini"></div>\n <div class="ainb-category-meta"><span>Last updated: </span><span>Generated by <a href="${mw.util.getUrl("User:DVRTed/AINB-helper")}">AINB-helper</a></span></div>\n </div>\n `);e.prepend(t),s.get({action:"query",prop:"revisions",titles:"User:DVRTed bot/AINB-stats.json",rvslots:"main",rvprop:"timestamp|content",format:"json",formatversion:"2"}).then(e=>{const i=e.query.pages[0].revisions[0],{active_cases:n,total_todo:s,total_in_progress:a,total_completed:o,total_unnecessary:r}=JSON.parse(i.slots.main.content),l=s+a+o+r,d=o+r,c=Math.round(d/l*100);t.find(".ainb-category-meta span").first().text(`Last updated: ${new Date(i.timestamp).toLocaleString([],{month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit",timeZone:"UTC",timeZoneName:"short"})}`);const p=[{key:"todo",count:s},{key:"completed",count:o},{key:"unnecessary",count:r},{key:"ongoing",count:a}].filter(({count:e})=>e>0),g=p.map(({key:e,count:t})=>`<div class="ainb-seg ainb-seg-${e}" style="width:${t/l*100}%" title="${e}: ${t.toLocaleString()}"></div>`).join(""),_=p.map(({key:e,count:t})=>`<span><i class="ainb-dot ainb-seg-${e}"></i>${e} (${t.toLocaleString()})</span>`).join("");t.find(".ainb-progress-bar").html(g),t.find(".ainb-progress-percent").text(`${c}%`),t.find(".ainb-progress-stats").text(`${d.toLocaleString()} / ${l.toLocaleString()} resolved`),t.find(".ainb-progress-legend").html(_),t.find(".ainb-category-mini").html(`There are <strong>${n.toLocaleString()}</strong> active cases with <strong>${s.toLocaleString()}</strong> pages marked as to-do, <strong>${a.toLocaleString()}</strong> in progress, <strong>${o.toLocaleString()}</strong> done, and <strong>${r.toLocaleString()}</strong> unnecessary.`)}).catch(()=>{t.find(".ainb-progress-stats").text("Could not load AINB stats")})}(),mw.loader.load("//en.wikipedia.org/w/index.php?title=User:DVRTed/AINB-helper.css&action=raw&ctype=text/css","text/css"),mw.util.addCSS("\n .ainb-progress-wrap { margin-bottom: 1em; padding: 8px 12px; border: 1px solid var(--border-color-base, #a2a9b1); border-radius: 4px; }\n .ainb-progress-top { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }\n .ainb-progress-percent { font-size: 1.8em; font-weight: 700; line-height: 1; color: var(--color-base, #202122); }\n .ainb-progress-top-text { display: flex; flex-direction: column; }\n .ainb-progress-title { font-weight: 600; font-size: 0.9em; }\n .ainb-progress-stats { font-size: 0.85em; color: var(--color-subtle, #54595d); }\n .ainb-progress-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: #eaecf0; }\n .ainb-seg { height: 100%; }\n .ainb-seg-completed { background: var(--background-color-success, #14866d); }\n .ainb-seg-unnecessary, .ainb-seg-unknown { background: var(--background-color-disabled, #c8ccd1); }\n .ainb-seg-ongoing { background: var(--background-color-progressive, #36c); }\n .ainb-seg-todo { background: var(--background-color-notice, #fc3); }\n .ainb-progress-legend { display: flex; gap: 10px; margin-top: 6px; font-size: 0.8em; color: var(--color-subtle, #54595d); text-transform: capitalize; }\n .ainb-progress-legend i.ainb-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 3px; }\n .ainb-progress-credit { font-size: 0.75em; color: var(--color-subtle, #54595d); font-weight: normal; text-align: right; }\n .ainb-progress-hide-row { margin-top: 6px; font-size: 0.85em; }\n .ainb-hide-resolved .ainb-row-resolved { display: none; }\n ");const r=mw.util.addPortletLink("p-tb","#","New AINB tracking","t-ainb-tracking","Generate tracking subpage for AINB");$(r).on("click",function(e){e.preventDefault(),function create_main_app(){const{nextTick:e}=a;create_app({template:'\n<div>\n<cdx-dialog class="ainb-helper" v-model:open="is_open" \n:title="dialog_title" :use-close-button="true"\n@update:open="handle_dialog_close">\n \n<div v-if="step === 1" class="ainb-step">\n <div v-if="!loading">\n <p>Enter the username</p>\n <cdx-text-input v-model="username" autocomplete="off" data-bwignore="true" data-lpignore="true" data-1p-ignore\n placeholder="User:ExampleUser or ExampleUser" @keydown.enter="fetch_contributions" />\n\n <div class="ainb-date-field">\n <label for="ainb-anchor-date">Only fetch edits made after:</label>\n <input id="ainb-anchor-date" type="date" v-model="anchor_date" class="ainb-date-input" />\n <p class="ainb-date-hint">Defaults to December 2022, the public release date of ChatGPT.</p>\n </div>\n\n <div class="ainb-date-field">\n <label for="ainb-end-date">Only fetch edits made before:</label>\n <input id="ainb-end-date" type="date" v-model="end_date" class="ainb-date-input" />\n <p class="ainb-date-hint">Leave blank to fetch up to the most recent edit.</p>\n </div>\n </div>\n\n <div v-if="error" class="ainb-error">{{ error }}</div>\n\n <div v-if="loading" class="ainb-loading">\n <p>Fetching contributions... {{ progress > 0 ? progress + \' found\' : \'\' }}</p>\n <cdx-progress-bar inline></cdx-progress-bar>\n </div>\n</div>\n \n \n<div v-if="step === 2" class="ainb-step2">\n <div class="ainb-step2-subtitle">\n <template v-if="is_multiple_users">Multiple users</template>\n <template v-else>\n <a :href="get_user_url(normalized_username)" target="_blank">User:{{ normalized_username }}</a>\n · <a :href="get_contribs_url(normalized_username)" target="_blank">(contrib)</a>\n </template>\n · {{ edit_count }} edit(s) across {{ article_groups.length }} article(s)\n </div>\n <div class="ainb-step2-toolbar">\n <cdx-checkbox :model-value="all_selected" :indeterminate="some_selected && !all_selected"\n @update:model-value="toggle_all">Select all</cdx-checkbox>\n <cdx-menu-button v-model:selected="filter_menu_selected" weight="normal" :menu-items="filter_menu_items"\n :disabled="!some_selected" @update:selected="handle_filter_menu_select">Filter selected</cdx-menu-button>\n <span class="ainb-total-badge"><b>{{ total_selected }}</b> of {{ total_groups }} articles selected</span>\n </div>\n\n <div v-if="notes_visible" class="ainb-notes-field">\n <label for="ainb-extra-notes">Notes for tracking page (e.g., applied filters)</label>\n <textarea id="ainb-extra-notes" v-model="extra_notes" rows="3"\n placeholder="Text to be added above the tracker..."></textarea>\n </div>\n <cdx-button v-else weight="quiet" class="ainb-add-note-btn" @click="notes_visible = true">+ Add a note</cdx-button>\n\n <div class="ainb-step2-layout">\n <div class="ainb-article-list">\n <div class="ainb-article-list-controls">\n <cdx-text-input v-model="article_search" placeholder="Filter articles..."\n class="ainb-article-search"></cdx-text-input>\n <div class="ainb-sort-toggle">\n <button type="button" :class="{ active: sort_mode === \'edits\' }" @click="sort_mode = \'edits\'">Most\n edits</button>\n <button type="button" :class="{ active: sort_mode === \'alpha\' }"\n @click="sort_mode = \'alpha\'">A-Z</button>\n <button type="button" :class="{ active: sort_mode === \'recent\' }"\n @click="sort_mode = \'recent\'">Recent</button>\n </div>\n </div>\n\n <ul class="ainb-article-items">\n <li v-for="group in filtered_sorted_groups" :key="group.title" class="ainb-article-item"\n :class="{ \'ainb-article-item-active\': group.title === selected_article_title, \'ainb-article-item-picked\': group.selected_count > 0 }"\n @click="select_article(group.title)">\n <cdx-checkbox :model-value="group.all_selected"\n :indeterminate="group.some_selected && !group.all_selected"\n @update:model-value="toggle_article(group)" @click.stop></cdx-checkbox>\n <div class="ainb-article-item-info">\n <div class="ainb-article-item-title">{{ group.title }}</div>\n <div class="ainb-article-item-meta">\n <span>{{ group.edits.length }} edit(s)</span>\n <span v-if="group.selected_count > 0" class="ainb-article-item-badge">· selected {{\n group.selected_count }}/{{ group.edits.length }}</span>\n </div>\n </div>\n </li>\n <li v-if="filtered_sorted_groups.length === 0" class="ainb-article-empty">No articles match "{{\n article_search }}"</li>\n </ul>\n </div>\n\n <div class="ainb-revisions-panel">\n <template v-if="selected_group">\n <div class="ainb-revisions-header">\n <div>\n <div class="ainb-revisions-title">\n <a :href="get_article_url(selected_group.title)" target="_blank">{{ selected_group.title\n }}</a>\n <a :href="get_history_url(selected_group.title)" target="_blank"\n class="ainb-history-link">(hist)</a>\n </div>\n\n <div class="ainb-revisions-subtitle">\n {{ selected_group.edits.length }} edit(s) by {{ get_group_users(selected_group) }}\n </div>\n </div>\n </div>\n\n <table class="ainb-revisions-table">\n <thead>\n <tr>\n <th class="ainb-col-cb"></th>\n <th class="ainb-col-actions">Diff</th>\n <th class="ainb-col-time">Date</th>\n <th class="ainb-col-size">Size</th>\n <th class="ainb-col-summary">Summary</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for="edit in selected_group.edits" :key="edit.revid" class="ainb-diff-row"\n :class="{ \'ainb-diff-row-selected\': edit.selected }">\n <td class="ainb-col-cb">\n <cdx-checkbox v-model="edit.selected"\n @update:model-value="update_group_selection(selected_group)"></cdx-checkbox>\n </td>\n <td class="ainb-col-actions">\n <button type="button" class="ainb-diff-toggle" @click="show_diff_popup(edit)">View\n diff</button>\n <a :href="get_diff_url(edit.revid)" target="_blank" class="ainb-diff-extlink"\n title="Open in new tab">↗</a>\n </td>\n <td class="ainb-col-time" :title="edit.timestamp">{{ format_date(edit.timestamp) }}</td>\n <td :class="[\'ainb-col-size\', get_size_class(edit.sizediff)]">{{ format_bytes(edit.sizediff)\n }}</td>\n <td class="ainb-col-summary" :title="edit.comment">{{ edit.comment ? truncate(edit.comment,\n 80) : \'No edit summary\' }}</td>\n </tr>\n </tbody>\n </table>\n </template>\n <div v-else class="ainb-revisions-empty">Select an article on the left to view its revisions.</div>\n </div>\n </div>\n</div>\n \n \n<div v-if="step === 3" class="ainb-step">\n <div v-if="creating" class="ainb-loading">\n <p>Creating page...</p>\n <cdx-progress-bar inline></cdx-progress-bar>\n </div>\n\n <div v-else-if="create_error" class="ainb-error">{{ create_error }}</div>\n\n <div v-else>\n <p>Page created successfully!</p>\n <p><a :href="target_page_url" target="_blank">{{ target_page_title }}</a></p>\n </div>\n</div>\n \n \n<template #footer>\n <div class="ainb-dialog-footer">\n <div v-if="step === 1"></div>\n\n <cdx-button v-if="step === 1" action="progressive" weight="primary" @click="fetch_contributions"\n :disabled="loading || !username">\n {{ loading ? \'Fetching...\' : \'Fetch contributions\' }}</cdx-button>\n\n <template v-if="step === 2">\n <div class="ainb-subpage-info">Target: <strong>{{ target_page_title }}</strong></div>\n <div class="ainb-footer-buttons">\n <cdx-button @click="step = 1">Back</cdx-button>\n <cdx-button @click="copy_wikitext" :disabled="total_selected_diffs === 0">Copy wikitext\n </cdx-button>\n <cdx-button action="progressive" weight="primary" @click="generate_report"\n :disabled="total_selected_diffs === 0">Create Page\n </cdx-button>\n </div>\n </template>\n\n <template v-if="step === 3">\n <div></div>\n <div>\n <cdx-button @click="handle_dialog_close">Close</cdx-button>\n </div>\n </template>\n </div>\n</template>\n \n</cdx-dialog>\n\n<cdx-dialog v-model:open="diff_dialog_open" :title="viewing_diff_edit ? \'Diff for \' + viewing_diff_edit.title : \'\'"\n :use-close-button="true" class="ainb-diff-dialog" @keyup.left="go_to_diff(-1)" @keyup.right="go_to_diff(1)">\n <div v-if="viewing_diff_edit" class="ainb-diff-dialog-body">\n <div class="ainb-diff-meta">\n <select class="ainb-diff-select" :value="viewing_diff_edit.revid"\n @change="jump_to_diff($event.target.value)" v-if="selected_group.edits.length > 1">\n <option v-for="(e, idx) in selected_group.edits" :key="e.revid" :value="e.revid">\n {{ idx + 1 }} / {{ selected_group.edits.length }} — {{ format_date(e.timestamp) }} ({{\n format_bytes(e.sizediff) }})\n </option>\n </select>\n <a :href="get_diff_url(viewing_diff_edit.revid)" target="_blank" class="ainb-diff-meta-link">Open in new tab\n ↗</a>\n </div>\n <div class="ainb-diff-meta-include">\n <cdx-checkbox v-model="viewing_diff_edit.selected"\n @update:model-value="update_group_selection(selected_group)">Include</cdx-checkbox>\n </div>\n <div class="ainb-diff-meta-comment" :title="viewing_diff_edit.comment"><span :class="[\'ainb-diff-meta-size\', get_size_class(viewing_diff_edit.sizediff)]">{{\n format_bytes(viewing_diff_edit.sizediff) }} bytes</span> · <span\n class="ainb-diff-meta-comment-label">Summary:</span> {{ viewing_diff_edit.comment || \'No edit summary\'\n }}</div>\n\n <div v-if="viewing_diff_edit.diff_loading" class="ainb-diff-loading">Loading diff...</div>\n <div v-else-if="viewing_diff_edit.diff_content" class="ainb-diff-content"\n v-html="viewing_diff_edit.diff_content"></div>\n <div v-else class="ainb-diff-loading">No content loaded.</div>\n </div>\n <template #footer>\n <div class="ainb-dialog-footer">\n <div class="ainb-diff-nav">\n <cdx-button @click="go_to_diff(-1)" :disabled="!has_prev_diff">← Prev</cdx-button>\n <cdx-button @click="go_to_diff(1)" :disabled="!has_next_diff">Next →</cdx-button>\n </div>\n <cdx-button @click="close_diff_popup">Close</cdx-button>\n </div>\n </template>\n</cdx-dialog>\n \n\n<cdx-dialog v-model:open="tag_dialog_open" title="Unselect edits by tag" :use-close-button="true"\n class="ainb-tag-dialog">\n <p v-if="tags_in_selection.length === 0">No tags found on the selected edits.</p>\n <div v-else>\n <cdx-checkbox v-for="tag in tags_in_selection" :key="tag" v-model="selected_tags_map[tag]">\n {{ tag }} ({{ tag_counts[tag] }} edit{{ tag_counts[tag] === 1 ? \'\' : \'s\' }})\n </cdx-checkbox>\n </div>\n <template #footer>\n <div class="ainb-dialog-footer">\n <div></div>\n <div>\n <cdx-button @click="tag_dialog_open = false">Cancel</cdx-button>\n <cdx-button action="progressive" weight="primary" @click="unselect_by_tag"\n :disabled="selected_tag_list.length === 0">\n Unselect\n </cdx-button>\n </div>\n </div>\n </template>\n</cdx-dialog>\n \n</div>\n ',data:()=>({is_open:!0,step:1,username:"",normalized_username:"",normalized_usernames:[],anchor_date:"2022-12-01",end_date:"",loading:!1,progress:0,edit_count:0,error:"",article_groups:[],article_search:"",sort_mode:"recent",selected_article_title:"",creating:!1,create_error:"",generated_wikitext:"",target_page_title:"",target_page_url:"",viewing_diff_edit:null,filter_menu_selected:null,available_tags:[],selected_tags_map:{},tag_dialog_open:!1,tag_counts:{},extra_notes:"",notes_visible:!1}),computed:{dialog_title(){return 1===this.step?"Generate tracking subpage for AINB":2===this.step?"Select diffs to include":"Page Created"},total_selected_diffs(){return this.article_groups.reduce((e,t)=>e+t.selected_count,0)},total_selected(){return this.article_groups.filter(e=>e.selected_count>0).length},total_groups(){return this.article_groups.length},all_selected(){return this.article_groups.length>0&&this.article_groups.every(e=>e.all_selected)},some_selected(){return this.article_groups.some(e=>e.some_selected||e.all_selected)},current_date:()=>(new Date).toISOString().split("T")[0],diff_dialog_open:{get(){return!!this.viewing_diff_edit},set(e){e||(this.viewing_diff_edit=null)}},diff_edit_index(){return this.selected_group&&this.viewing_diff_edit?this.selected_group.edits.findIndex(e=>e.revid===this.viewing_diff_edit.revid):-1},has_prev_diff(){return this.diff_edit_index>0},has_next_diff(){return this.diff_edit_index>=0&&this.selected_group&&this.diff_edit_index<this.selected_group.edits.length-1},filtered_sorted_groups(){let e=this.article_groups;const t=this.article_search.trim().toLowerCase();return t&&(e=e.filter(e=>e.title.toLowerCase().includes(t))),e=[...e],"edits"===this.sort_mode?e.sort((e,t)=>t.edits.length-e.edits.length):"alpha"===this.sort_mode?e.sort((e,t)=>e.title.localeCompare(t.title)):"recent"===this.sort_mode&&e.sort((e,t)=>new Date(t.edits[0].timestamp)-new Date(e.edits[0].timestamp)),e},selected_group(){return this.article_groups.find(e=>e.title===this.selected_article_title)||null},filter_menu_items:()=>[{value:"smaller",label:"Unselect smaller edits"},{value:"tag",label:"Unselect edits by tag"},{value:"non_creations",label:"Unselect non-creations"}],selected_tag_list(){return this.available_tags.filter(e=>this.selected_tags_map[e])},tags_in_selection(){return this.available_tags.filter(e=>(this.tag_counts[e]||0)>0)},is_multiple_users(){return this.normalized_usernames.length>1}},methods:{fire_hook(t){e(()=>{const e=$(t);e.length&&mw.hook("wikipage.content").fire(e)})},select_article(e){this.selected_article_title=e,this.fire_hook(".ainb-revisions-table")},update_group_selection(e){const t=e.edits.filter(e=>e.selected).length;e.selected_count=t,e.all_selected=t===e.edits.length,e.some_selected=t>0&&t<e.edits.length},toggle_article(e){const t=!e.all_selected;e.edits.forEach(e=>e.selected=t),this.update_group_selection(e)},toggle_all(){const e=!this.all_selected;this.article_groups.forEach(t=>{t.edits.forEach(t=>t.selected=e),this.update_group_selection(t)})},append_filter_note(e){const t=`* ${e}`;this.extra_notes=this.extra_notes?`${this.extra_notes}\n${t}`:t,this.notes_visible=!0},unselect_smaller_edits(){const e=prompt("Unselect edits smaller than (bytes):","35");if(null===e)return;const t=parseInt(e,10);isNaN(t)||(this.article_groups.forEach(e=>{e.edits.forEach(e=>{e.selected&&Math.abs(e.sizediff)<t&&(e.selected=!1)}),this.update_group_selection(e)}),this.append_filter_note(`Edits smaller than +/- ${t} bytes were excluded.`))},handle_filter_menu_select(e){this.filter_menu_selected=null,"smaller"===e?this.unselect_smaller_edits():"tag"===e?this.open_tag_dialog():"non_creations"===e&&this.unselect_non_creations()},unselect_non_creations(){this.article_groups.forEach(e=>{e.edits.forEach(e=>{const t=void 0!==e.new;e.selected&&!t&&(e.selected=!1)}),this.update_group_selection(e)}),this.append_filter_note("Non-creation edits were excluded.")},open_tag_dialog(){this.selected_tags_map=Object.fromEntries(this.available_tags.map(e=>[e,!1]));const e={};this.article_groups.forEach(t=>{t.edits.forEach(t=>{t.selected&&(t.tags||[]).forEach(t=>{e[t]=(e[t]||0)+1})})}),this.tag_counts=e,this.tag_dialog_open=!0},unselect_by_tag(){const e=new Set(this.selected_tag_list);this.article_groups.forEach(t=>{t.edits.forEach(t=>{t.selected&&t.tags?.some(t=>e.has(t))&&(t.selected=!1)}),this.update_group_selection(t)}),this.append_filter_note(`Edits tagged "${[...e].join('", "')}" were excluded.`),this.tag_dialog_open=!1},async fetch_contributions(){this.loading=!0,this.error="",this.progress=0,this.extra_notes="",this.notes_visible=!1;try{const e=[];let t=null;const i=this.username.split("|").map(e=>e.trim().replace(/^user:/i,"")).filter(Boolean);if(0===i.length)return void(this.error="Please enter a username.");const n=await s.get({action:"query",list:"users",ususers:i.join("|"),usprop:"editcount"}),a=n.query?.users||[],o=a.reduce((e,t)=>e+(t.editcount||0),0);if(o>2e4){if(!confirm(`User has over 20k edits (${o}). Are you sure you want to continue?`))return void(this.error="Manually cancelled: User has too many edits.")}else if(!o)return void(this.error="No edits found in the timeframe. Note: the username is case-sensitive.");const r=a.filter(e=>e.name&&!e.missing&&!e.invalid).map(e=>e.name);if(this.normalized_usernames=r,this.normalized_username=r[0]||"",r.length>1){const e=r.map(e=>`[[User:${e}]]`).join(", ");this.extra_notes=`* Includes contributions from multiple accounts: ${e}`,this.notes_visible=!0}const l=this.anchor_date?`${this.anchor_date}T00:00:00Z`:void 0,d=this.end_date?`${this.end_date}T00:00:00Z`:void 0;do{const i={action:"query",list:"usercontribs",ucnamespace:0,ucuser:r.join("|"),...l?{ucend:l}:{},...d?{ucstart:d}:{},uclimit:"max",ucprop:"ids|title|timestamp|comment|sizediff|tags|flags|user",ucdir:"older",...t},n=await s.get(i);if(n.error)throw new Error(n.error.info);e.push(...n.query.usercontribs),this.progress=e.length,t=n.continue}while(t);const c=e.filter(e=>!e.tags?.includes("mw-reverted")),p={};c.forEach(e=>{p[e.title]||(p[e.title]={title:e.title,edits:[],all_selected:!1,some_selected:!1,selected_count:0}),p[e.title].edits.push({...e,selected:!1,diff_loading:!1,diff_content:""})}),this.edit_count=c.length;const g=new Set;if(c.forEach(e=>{(e.tags||[]).forEach(e=>g.add(e))}),this.available_tags=Array.from(g).sort(),this.article_groups=Object.values(p),this.article_groups.forEach(e=>this.update_group_selection(e)),0===this.article_groups.length)this.error="No contributions found in the specified period.";else{this.step=2;const e=this.filtered_sorted_groups[0];e&&this.select_article(e.title);const t=`Wikipedia:AI noticeboard/${this.current_date} ${this.normalized_username}`;this.target_page_title=t,this.target_page_url=mw.util.getUrl(t)}}catch(e){this.error="Error fetching contributions: "+e.message,console.error(e)}finally{this.loading=!1}},show_diff_popup(e){this.viewing_diff_edit=e,this.load_diff(e)},close_diff_popup(){this.viewing_diff_edit=null},go_to_diff(e){if(!this.selected_group||this.diff_edit_index<0)return;const t=this.selected_group.edits[this.diff_edit_index+e];t&&this.show_diff_popup(t)},jump_to_diff(e){if(!this.selected_group)return;const t=this.selected_group.edits.find(t=>t.revid==e);t&&this.show_diff_popup(t)},async load_diff(e){if(!e.diff_content&&!e.diff_loading){e.diff_loading=!0;try{const t=await s.get({action:"compare",fromrev:e.revid,torelative:"prev",prop:"diff"});t.compare?.["*"]?e.diff_content=`<table class="diff">${t.compare["*"]}</table>`:e.diff_content="<p>Could not load diff.</p>"}catch(t){console.error("Error loading diff:",t),e.diff_content="<p>Error loading diff: "+t.message+"</p>"}finally{e.diff_loading=!1}}},async generate_report(){const e=this.build_wikitext();this.generated_wikitext=e,this.creating=!0,this.create_error="",this.step=3;try{await s.postWithEditToken({action:"edit",title:this.target_page_title,text:e,summary:`Creating tracking subpage ${t}`})}catch(e){this.create_error="Error creating page: "+e.message,console.error(e)}finally{this.creating=!1}},build_wikitext(){const e=this.article_groups.map(e=>({...e,edits:e.edits.filter(e=>e.selected)})).filter(e=>e.edits.length>0);let t="{{NOINDEX|visible=yes}}\nRelevant report and discussion may be viewable on the talk page.\n\n";return t+="== Tracking list ==\n",this.extra_notes.trim()&&(t+=`{{Notice |heading=Notes |\n${this.extra_notes.trim()}\n}}\n\n`),t+="{{AIC article list|\n",e.forEach(e=>{const i=e.edits.map(e=>{const t=this.format_bytes(e.sizediff);return`[[Special:Diff/${e.revid}|(${t})]]${void 0!==e.new?" (page created)":""}`}).join(" "),n=e.edits.length,s=n>1?"edits":"edit";t+=`{{AIC article row|article=${e.title}|status=requested|notes=${n} ${s}: ${i}}}\n`}),t+="}}\n",t},async copy_wikitext(){try{await navigator.clipboard.writeText(this.build_wikitext()),mw.notify("Wikitext copied to clipboard.",{type:"success"})}catch(e){mw.notify("Failed to copy to clipboard.",{type:"error"})}},get_diff_url:e=>mw.util.getUrl(`Special:Diff/${e}`),get_article_url:e=>mw.util.getUrl(e),get_history_url:e=>mw.util.getUrl(e,{action:"history"}),get_user_url:e=>mw.util.getUrl(`User:${e}`),get_contribs_url:e=>mw.util.getUrl(`Special:Contributions/${e}`),get_group_users(e){if(!e?.edits)return"";const t=[...new Set(e.edits.map(e=>e.user).filter(Boolean))];return t.length?t.join(", "):this.normalized_username},format_bytes:e=>(e>0?"+":"")+(e||0),format_date(e){if(!e)return"";const t=new Date(e);return isNaN(t.getTime())?e:t.toLocaleString(void 0,{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})},get_size_class:e=>e>0?"ainb-pos":e<0?"ainb-neg":"ainb-neu",truncate:(e,t)=>e?.length>t?e.slice(0,t-1)+"...":e||""}})}()});const l=mw.config.get("wgPageName");if((l.startsWith("Wikipedia:AI_noticeboard/")||l===i)&&(!function init_progress_bar(){const e=["completed","unnecessary","ongoing","todo","unknown"];$("table").has('tr[class*="aic-row-"]').each(function(){const t=$(this),i=Object.fromEntries(e.map(e=>[e,0]));t.find('tr[class*="aic-row-"]').each(function(){const e=function get_row_status(e){const t=e.attr("class")?.match(/\baic-row-(\S+)/);return t?t[1]:"unknown"}($(this)),t=e in i?e:"unknown";i[t]++,"completed"!==t&&"unnecessary"!==t||$(this).addClass("ainb-row-resolved")});const n=Object.values(i).reduce((e,t)=>e+t,0);if(!n)return;const s=i.completed+i.unnecessary,a=Math.round(s/n*100),o=e.filter(e=>i[e]>0),r=o.map(e=>`<div class="ainb-seg ainb-seg-${e}" style="width:${i[e]/n*100}%" title="${i[e]} ${e}"></div>`).join(""),l=o.map(e=>`<span><i class="ainb-dot ainb-seg-${e}"></i>${e} (${i[e]})</span>`).join(""),d=$(`\n <div class="ainb-progress-wrap">\n <div class="ainb-progress-top">\n <span class="ainb-progress-percent">${a}%</span>\n <div class="ainb-progress-top-text">\n <div class="ainb-progress-title">Progress</div>\n <div class="ainb-progress-stats">${s} / ${n} resolved</div>\n </div>\n </div>\n <div class="ainb-progress-bar">${r}</div>\n <div class="ainb-progress-legend">${l}</div>\n <div class="ainb-progress-credit">Generated by <a href="${mw.util.getUrl("User:DVRTed/AINB-helper")}">AINB-helper</a></div>\n <div class="ainb-progress-hide-row">\n <label><input type="checkbox" class="ainb-hide-resolved-cb"> Hide resolved entries</label>\n </div>\n </div>\n `);d.find(".ainb-hide-resolved-cb").on("change",function(){t.toggleClass("ainb-hide-resolved",$(this).is(":checked"))}),t.before(d)})}(),function init_row_editing(){$("table").has('tr[class*="aic-row-"]').each(function(){const e=$(this);e.find("thead").find("tr").prepend('<th class="ainb-action-header">Action</th>');const t=e.find('tr[class*="aic-row-"]').map(function(){return $(this).find("a").first().text().trim()}).get().filter(Boolean);if(t.length){const i=$('<button type="button" class="cdx-button cdx-button--action-progressive">').text("Batch edit").on("click",e=>{e.preventDefault(),create_edit_table_app(t)});e.before(i)}e.find('tr[class*="aic-row-"]').each(function(){const e=$(this).find("td").first(),t=e.find("a").first();if(!t.length)return;const i=$("<td>").addClass("ainb-action-cell");e.before(i);const n=$("<button>").addClass("ainb-edit-btn").text("✎").attr("title","Edit this row").on("click",e=>{e.preventDefault(),create_edit_table_app(t.text().trim())});i.append(n)})})}()),[0,118].includes(mw.config.get("wgNamespaceNumber"))){const e=mw.util.addPortletLink("p-cactions","#","LLM tag/prod","t-llm-tag-prod","LLM tag/prod helper");$(e).on("click",function(e){e.preventDefault(),function create_llm_tag_prod_app(){const e=[],i="ainb-llm-tag-last-thread";create_app({template:'\n<div>\n <cdx-dialog class="ainb-llm-dialog" v-model:open="is_open" \n title="LLM tag / prod" :use-close-button="true"\n @update:open="handle_dialog_close">\n \n <div v-if="step === 1">\n <div v-if="step1_error" class="ainb-error">{{ step1_error }}</div>\n <cdx-field>\n <cdx-radio v-model="selected_option" input-value="llm_prod" :inline="true" :disabled="checking_page">\n Prod LLM\n </cdx-radio>\n <cdx-radio v-model="selected_option" input-value="ai_tag" :inline="true" :disabled="checking_page">\n Add {{AI-generated}} tag\n </cdx-radio>\n </cdx-field>\n\n <cdx-field>\n <template #description>Tip: Type the username to autocomplete from Wikipedia:AI noticeboard. You can leave this blank to proceed anyway.</template>\n <cdx-combobox v-model:selected="subpage" :menu-items="filtered_subpage_options" placeholder="Relevant thread or subpage (optional)" :disabled="checking_page"></cdx-combobox>\n </cdx-field>\n </div>\n\n <div v-if="step === 2">\n <div class="ainb-thread-context">\n <span>Thread: <strong>{{ subpage }}</strong></span>\n <a href="#" @click.prevent="go_back_to_step1">Change</a>\n </div>\n <div v-if="save_error" class="ainb-error">{{ save_error }}</div>\n\n <cdx-field>\n <template #label>Resulting wikitext:</template>\n <cdx-text-area v-model="editable_wikitext" rows="5" :disabled="saving"></cdx-text-area>\n </cdx-field>\n\n <div class="ainb-preview-link-wrap">\n <a href="#" @click.prevent="toggle_preview">\n {{ show_preview ? \'Hide preview\' : \'Show preview\' }}\n </a>\n </div>\n\n <div v-if="show_preview" class="ainb-preview-box">\n <div v-if="preview_loading" class="ainb-loading">Loading preview...</div>\n <div v-else class="ainb-preview-content" v-html="preview_html"></div>\n </div>\n\n <cdx-field>\n <template #label>Edit summary:</template>\n <cdx-text-input v-model="editable_summary" :disabled="saving" />\n </cdx-field>\n </div>\n\n <template #footer>\n <div class="ainb-dialog-footer">\n <div v-if="step === 1">\n <cdx-button @click="handle_dialog_close">Cancel</cdx-button>\n </div>\n <div v-if="step === 1">\n <cdx-button action="progressive" weight="primary" @click="go_to_step2" :disabled="checking_page">\n {{ checking_page ? \'Checking...\' : \'Next\' }}\n </cdx-button>\n </div>\n\n <div v-if="step === 2">\n <cdx-button @click="go_back_to_step1" :disabled="saving">Back</cdx-button>\n </div>\n <div v-if="step === 2">\n <cdx-button action="progressive" weight="primary" @click="save_edit" :disabled="saving || !editable_wikitext">\n {{ saving ? \'Saving...\' : \'Submit edit\' }}\n </cdx-button>\n </div>\n </div>\n </template>\n </cdx-dialog>\n</div>\n ',data:()=>({is_open:!0,step:1,selected_option:"llm_prod",subpage:"",subpage_options:e,editable_wikitext:"",editable_summary:"",saving:!1,save_error:"",step1_error:"",checking_page:!1,show_preview:!1,preview_html:"",preview_loading:!1}),computed:{filtered_subpage_options(){const e=(this.subpage||"").trim().toLowerCase();return e?this.subpage_options.filter(t=>t.value.toLowerCase().includes(e)):this.subpage_options}},methods:{async go_to_step2(){let e=this.subpage.trim();if(this.step1_error="",e){this.checking_page=!0;const[t,...i]=e.split("#"),n=t.trim(),a=i.join("#").trim();try{const e=await s.get({action:"parse",page:n,prop:"sections",redirects:!0});if(a){if(!(e.parse?.sections||[]).some(e=>e.line===a||e.anchor===a||e.line.replace(/_/g," ")===a.replace(/_/g," ")))return void(this.step1_error=`Section "${a}" does not exist on "${n}"`)}}catch(e){return void(this.step1_error=`Page does not exist: "${e}"`)}finally{this.checking_page=!1}}let t=e;mw.storage.setObject(i,{subpage:e,selected_option:this.selected_option,ts:Date.now()});const n=t?`, see [[${t}]]`:"",a=t?` |reason= [[${t}]]`:"";"llm_prod"===this.selected_option?(this.editable_wikitext=`{{subst:Prod llm\n|reason=[[WP:LLMPRV|Presumptive removal of LLM-generated content]]${n}. Feel free to reinstate by following [[WP:LLMPRVOBJ|the procedures for disputing presumptive removal of LLM-generated content]].}}`,this.editable_summary=`[[WP:LLMPRV|Presumptive removal of LLM-generated content]]${n}. Feel free to reinstate by following [[WP:LLMPRVOBJ|the procedures for disputing presumptive removal of LLM-generated content]].`):(this.editable_wikitext=`{{AI-generated${a} |{{subst:DATE}}}}`,this.editable_summary=`Added AI tag${n}`),this.show_preview=!1,this.step=2},go_back_to_step1(){mw.storage.remove(i),this.step1_error="",this.step=1},async toggle_preview(){if(this.show_preview)this.show_preview=!1;else{this.preview_loading=!0,this.show_preview=!0;try{const e=await s.post({action:"parse",text:this.editable_wikitext,title:mw.config.get("wgPageName"),pst:!0,prop:"text"});e.parse?.text?.["*"]?this.preview_html=e.parse.text["*"]:this.preview_html="Could not generate preview."}catch(e){console.error("Preview error:",e),this.preview_html=`Preview error: ${e.message}`}finally{this.preview_loading=!1}}},async save_edit(){this.saving=!0,this.save_error="";try{const e=mw.config.get("wgPageName"),i=this.editable_wikitext.trim()+"\n",n=`${this.editable_summary.trim()} ${t}`;await s.postWithEditToken({action:"edit",title:e,prependtext:i,summary:n}),mw.notify("Edit submitted successfully!",{type:"success"}),location.reload(),this.handle_dialog_close()}catch(e){this.save_error="Error submitting edit: "+e,console.error(e)}finally{this.saving=!1}},async fetch_ainb_suggestions(){const e=[];try{const t=await s.get({action:"parse",page:"Wikipedia:AI noticeboard",prop:"sections",redirects:!0});t.parse?.sections&&t.parse.sections.forEach(t=>{e.push(`Wikipedia:AI noticeboard#${t.line}`)});const i=await s.get({action:"query",list:"prefixsearch",pssearch:"Wikipedia:AI noticeboard/",pslimit:100});i.query?.prefixsearch&&i.query.prefixsearch.forEach(t=>{e.push(t.title)})}catch(e){console.error("Error fetching AINB suggestions:",e)}return e}},mounted(){const e=mw.storage.getObject(i);e&&e.subpage&&Date.now()-e.ts<108e5&&(this.subpage=e.subpage,this.selected_option=e.selected_option||this.selected_option,this.go_to_step2()),this.fetch_ainb_suggestions().then(e=>{e.length>0&&(this.subpage_options=e.map(e=>({value:e,label:e})))})}})}()})}});
e5bt55tfgjqkiop82acgl641j8jeh15
762114
762113
2026-09-17T17:13:09Z
DVRTed
55993
762114
javascript
text/javascript
$(async () => {
// Userscript to help generating tracking subpages at [[WP:AINB]]
/* globals mw, $ */
// <nowiki>
const APP_ID = "ainb-helper";
const APP_AD = "(using [[User:DVRTed/AINB-helper|AINB-helper]])";
const DEBUG_MODE = false;
const DEBUG_PAGE = "User:DVRTed/sandbox2";
const require = mw.loader.require;
await mw.loader.using([
"vue",
"@wikimedia/codex",
"mediawiki.api",
"mediawiki.util",
]);
const api = new mw.Api();
const Vue = require("vue");
let current_app = null;
function close_app() {
if (current_app) {
current_app.unmount();
current_app = null;
}
document.getElementById(APP_ID)?.remove();
}
// reuseable function to create and mount the app
// that registers a bunch of components and handles dups
function create_app(App) {
const { createMwApp } = Vue;
const codex = require("@wikimedia/codex");
close_app();
const mount_point = document.createElement("div");
mount_point.id = APP_ID;
document.body.appendChild(mount_point);
const app = createMwApp({
...App,
mixins: [
{
methods: {
handle_dialog_close() {
close_app();
},
},
},
...(App.mixins || []),
],
});
const {
CdxButton,
CdxCheckbox,
CdxCombobox,
CdxDialog,
CdxField,
CdxMenuButton,
CdxProgressBar,
CdxRadio,
CdxSelect,
CdxTextArea,
CdxTextInput,
} = codex;
Object.entries({
CdxButton,
CdxCheckbox,
CdxCombobox,
CdxDialog,
CdxField,
CdxMenuButton,
CdxProgressBar,
CdxRadio,
CdxSelect,
CdxTextArea,
CdxTextInput,
}).forEach(([name, c]) => app.component(name, c));
app.mount(mount_point);
current_app = app;
}
function create_main_app() {
const { nextTick } = Vue;
create_app({
template: generate_main_template(),
data() {
return {
is_open: true,
step: 1,
username: "",
normalized_username: "",
normalized_usernames: [],
anchor_date: "2022-12-01",
end_date: "",
loading: false,
progress: 0,
edit_count: 0,
error: "",
article_groups: [],
article_search: "",
sort_mode: "recent",
selected_article_title: "",
creating: false,
create_error: "",
generated_wikitext: "",
target_page_title: "",
target_page_url: "",
viewing_diff_edit: null,
filter_menu_selected: null,
available_tags: [],
selected_tags_map: {},
tag_dialog_open: false,
tag_counts: {},
extra_notes: "",
notes_visible: false,
};
},
computed: {
dialog_title() {
if (this.step === 1) return "Generate tracking subpage for AINB";
if (this.step === 2) return "Select diffs to include";
return "Page Created";
},
total_selected_diffs() {
return this.article_groups.reduce(
(sum, group) => sum + group.selected_count,
0
);
},
total_selected() {
return this.article_groups.filter((group) => group.selected_count > 0)
.length;
},
total_groups() {
return this.article_groups.length;
},
all_selected() {
return (
this.article_groups.length > 0 &&
this.article_groups.every((group) => group.all_selected)
);
},
some_selected() {
return this.article_groups.some(
(group) => group.some_selected || group.all_selected
);
},
current_date() {
return new Date().toISOString().split("T")[0];
},
diff_dialog_open: {
get() {
return !!this.viewing_diff_edit;
},
set(val) {
if (!val) this.viewing_diff_edit = null;
},
},
diff_edit_index() {
if (!this.selected_group || !this.viewing_diff_edit) return -1;
return this.selected_group.edits.findIndex(
(edit) => edit.revid === this.viewing_diff_edit.revid
);
},
has_prev_diff() {
return this.diff_edit_index > 0;
},
has_next_diff() {
return (
this.diff_edit_index >= 0 &&
this.selected_group &&
this.diff_edit_index < this.selected_group.edits.length - 1
);
},
filtered_sorted_groups() {
let groups = this.article_groups;
const query = this.article_search.trim().toLowerCase();
if (query) {
groups = groups.filter((g) =>
g.title.toLowerCase().includes(query)
);
}
groups = [...groups];
if (this.sort_mode === "edits") {
groups.sort((a, b) => b.edits.length - a.edits.length);
} else if (this.sort_mode === "alpha") {
groups.sort((a, b) => a.title.localeCompare(b.title));
} else if (this.sort_mode === "recent") {
groups.sort(
(a, b) =>
new Date(b.edits[0].timestamp) - new Date(a.edits[0].timestamp)
);
}
return groups;
},
selected_group() {
return (
this.article_groups.find(
(g) => g.title === this.selected_article_title
) || null
);
},
filter_menu_items() {
return [
{ value: "smaller", label: "Unselect smaller edits" },
{ value: "tag", label: "Unselect edits by tag" },
{ value: "non_creations", label: "Unselect non-creations" },
];
},
selected_tag_list() {
return this.available_tags.filter(
(tag) => this.selected_tags_map[tag]
);
},
tags_in_selection() {
return this.available_tags.filter(
(tag) => (this.tag_counts[tag] || 0) > 0
);
},
is_multiple_users() {
return this.normalized_usernames.length > 1;
},
},
methods: {
fire_hook(selector) {
nextTick(() => {
const $content = $(selector);
if ($content.length) {
mw.hook("wikipage.content").fire($content);
}
});
},
select_article(title) {
this.selected_article_title = title;
this.fire_hook(".ainb-revisions-table");
},
update_group_selection(group) {
const selected = group.edits.filter((edit) => edit.selected).length;
group.selected_count = selected;
group.all_selected = selected === group.edits.length;
group.some_selected = selected > 0 && selected < group.edits.length;
},
toggle_article(group) {
const new_value = !group.all_selected;
group.edits.forEach((edit) => (edit.selected = new_value));
this.update_group_selection(group);
},
toggle_all() {
const new_value = !this.all_selected;
this.article_groups.forEach((group) => {
group.edits.forEach((edit) => (edit.selected = new_value));
this.update_group_selection(group);
});
},
append_filter_note(text) {
const line = `* ${text}`;
this.extra_notes = this.extra_notes
? `${this.extra_notes}\n${line}`
: line;
this.notes_visible = true;
},
unselect_smaller_edits() {
const input = prompt("Unselect edits smaller than (bytes):", "35");
if (input === null) return;
const threshold = parseInt(input, 10);
if (isNaN(threshold)) return;
this.article_groups.forEach((group) => {
group.edits.forEach((edit) => {
if (edit.selected && Math.abs(edit.sizediff) < threshold) {
edit.selected = false;
}
});
this.update_group_selection(group);
});
this.append_filter_note(
`Edits smaller than +/- ${threshold} bytes were excluded.`
);
},
handle_filter_menu_select(value) {
this.filter_menu_selected = null;
if (value === "smaller") {
this.unselect_smaller_edits();
} else if (value === "tag") {
this.open_tag_dialog();
} else if (value === "non_creations") {
this.unselect_non_creations();
}
},
unselect_non_creations() {
this.article_groups.forEach((group) => {
group.edits.forEach((edit) => {
const is_creation = edit.new !== undefined;
if (edit.selected && !is_creation) {
edit.selected = false;
}
});
this.update_group_selection(group);
});
this.append_filter_note("Non-creation edits were excluded.");
},
open_tag_dialog() {
this.selected_tags_map = Object.fromEntries(
this.available_tags.map((tag) => [tag, false])
);
const counts = {};
this.article_groups.forEach((group) => {
group.edits.forEach((edit) => {
if (!edit.selected) return;
(edit.tags || []).forEach((tag) => {
counts[tag] = (counts[tag] || 0) + 1;
});
});
});
this.tag_counts = counts;
this.tag_dialog_open = true;
},
unselect_by_tag() {
const tags_to_unselect = new Set(this.selected_tag_list);
this.article_groups.forEach((group) => {
group.edits.forEach((edit) => {
if (
edit.selected &&
edit.tags?.some((tag) => tags_to_unselect.has(tag))
) {
edit.selected = false;
}
});
this.update_group_selection(group);
});
this.append_filter_note(
`Edits tagged "${[...tags_to_unselect].join(
'", "'
)}" were excluded.`
);
this.tag_dialog_open = false;
},
async fetch_contributions() {
this.loading = true;
this.error = "";
this.progress = 0;
this.extra_notes = "";
this.notes_visible = false;
try {
const edits = [];
let continuation = null;
const raw_users = this.username
.split("|")
.map((u) => u.trim().replace(/^user:/i, ""))
.filter(Boolean);
if (raw_users.length === 0) {
this.error = "Please enter a username.";
return;
}
// check for users w/ too many edits
const user_info = await api.get({
action: "query",
list: "users",
ususers: raw_users.join("|"),
usprop: "editcount",
});
const users = user_info.query?.users || [];
const edit_count = users.reduce(
(sum, u) => sum + (u.editcount || 0),
0
);
if (edit_count > 20000) {
if (
!confirm(
`User has over 20k edits (${edit_count}). Are you sure you want to continue?`
)
) {
this.error = "Manually cancelled: User has too many edits.";
return;
}
} else if (!edit_count) {
this.error =
"No edits found in the timeframe. Note: the username is case-sensitive.";
return;
}
const normalized_users = users
.filter((u) => u.name && !u.missing && !u.invalid)
.map((u) => u.name);
this.normalized_usernames = normalized_users;
this.normalized_username = normalized_users[0] || "";
if (normalized_users.length > 1) {
const user_list = normalized_users
.map((u) => `[[User:${u}]]`)
.join(", ");
this.extra_notes = `* Includes contributions from multiple accounts: ${user_list}`;
this.notes_visible = true;
}
const ucend_timestamp = this.anchor_date
? `${this.anchor_date}T00:00:00Z`
: undefined;
const ucstart_timestamp = this.end_date
? `${this.end_date}T00:00:00Z`
: undefined;
do {
const params = {
action: "query",
list: "usercontribs",
ucnamespace: 0,
ucuser: normalized_users.join("|"),
...(ucend_timestamp ? { ucend: ucend_timestamp } : {}),
...(ucstart_timestamp ? { ucstart: ucstart_timestamp } : {}),
uclimit: "max",
ucprop: "ids|title|timestamp|comment|sizediff|tags|flags|user",
ucdir: "older",
...continuation,
};
const response = await api.get(params);
if (response.error) throw new Error(response.error.info);
edits.push(...response.query.usercontribs);
this.progress = edits.length;
continuation = response.continue;
} while (continuation);
const valid_edits = edits.filter(
(edit) => !edit.tags?.includes("mw-reverted")
);
const groups = {};
valid_edits.forEach((edit) => {
if (!groups[edit.title]) {
groups[edit.title] = {
title: edit.title,
edits: [],
all_selected: false,
some_selected: false,
selected_count: 0,
};
}
groups[edit.title].edits.push({
...edit,
selected: false,
diff_loading: false,
diff_content: "",
});
});
this.edit_count = valid_edits.length;
const tag_set = new Set();
valid_edits.forEach((edit) => {
(edit.tags || []).forEach((tag) => tag_set.add(tag));
});
this.available_tags = Array.from(tag_set).sort();
this.article_groups = Object.values(groups);
this.article_groups.forEach((group) =>
this.update_group_selection(group)
);
if (this.article_groups.length === 0) {
this.error = "No contributions found in the specified period.";
} else {
this.step = 2;
const top_article = this.filtered_sorted_groups[0];
if (top_article) this.select_article(top_article.title);
const page_title = DEBUG_MODE
? DEBUG_PAGE
: `Wikipedia:AI noticeboard/${this.current_date} ${this.normalized_username}`;
this.target_page_title = page_title;
this.target_page_url = mw.util.getUrl(page_title);
}
} catch (error) {
this.error = "Error fetching contributions: " + error.message;
console.error(error);
} finally {
this.loading = false;
}
},
show_diff_popup(edit) {
this.viewing_diff_edit = edit;
this.load_diff(edit);
},
close_diff_popup() {
this.viewing_diff_edit = null;
},
go_to_diff(offset) {
if (!this.selected_group || this.diff_edit_index < 0) return;
const next_edit =
this.selected_group.edits[this.diff_edit_index + offset];
if (next_edit) this.show_diff_popup(next_edit);
},
jump_to_diff(revid) {
if (!this.selected_group) return;
const edit = this.selected_group.edits.find((e) => e.revid == revid);
if (edit) this.show_diff_popup(edit);
},
async load_diff(edit) {
if (edit.diff_content || edit.diff_loading) return;
edit.diff_loading = true;
try {
const response = await api.get({
action: "compare",
fromrev: edit.revid,
torelative: "prev",
prop: "diff",
});
if (response.compare?.["*"]) {
edit.diff_content = `<table class="diff">${response.compare["*"]}</table>`;
} else {
edit.diff_content = "<p>Could not load diff.</p>";
}
} catch (error) {
console.error("Error loading diff:", error);
edit.diff_content =
"<p>Error loading diff: " + error.message + "</p>";
} finally {
edit.diff_loading = false;
}
},
async generate_report() {
const wikitext = this.build_wikitext();
this.generated_wikitext = wikitext;
this.creating = true;
this.create_error = "";
this.step = 3;
try {
await api.postWithEditToken({
action: "edit",
title: this.target_page_title,
text: wikitext,
summary: `Creating tracking subpage ${APP_AD}`,
});
} catch (error) {
this.create_error = "Error creating page: " + error.message;
console.error(error);
} finally {
this.creating = false;
}
},
build_wikitext() {
const selected_groups = this.article_groups
.map((group) => ({
...group,
edits: group.edits.filter((edit) => edit.selected),
}))
.filter((group) => group.edits.length > 0);
let wikitext = `{{NOINDEX|visible=yes}}\nRelevant report and discussion may be viewable on the talk page.\n\n`;
wikitext += `== Tracking list ==\n`;
if (this.extra_notes.trim()) {
wikitext += `{{Notice |heading=Notes |\n${this.extra_notes.trim()}\n}}\n\n`;
}
wikitext += `{{AIC article list|\n`;
selected_groups.forEach((group) => {
const links = group.edits
.map((edit) => {
const edit_size = this.format_bytes(edit.sizediff);
const edit_link = `[[Special:Diff/${edit.revid}|(${edit_size})]]`;
const creation_note =
edit.new !== undefined ? " (page created)" : "";
return `${edit_link}${creation_note}`;
})
.join(" ");
const edit_count = group.edits.length;
const edit_str = edit_count > 1 ? "edits" : "edit";
wikitext += `{{AIC article row|article=${group.title}|status=requested|notes=${edit_count} ${edit_str}: ${links}}}\n`;
});
wikitext += `}}\n`;
return wikitext;
},
async copy_wikitext() {
try {
await navigator.clipboard.writeText(this.build_wikitext());
mw.notify("Wikitext copied to clipboard.", { type: "success" });
} catch (err) {
mw.notify("Failed to copy to clipboard.", { type: "error" });
}
},
get_diff_url(revid) {
return mw.util.getUrl(`Special:Diff/${revid}`);
},
get_article_url(title) {
return mw.util.getUrl(title);
},
get_history_url(title) {
return mw.util.getUrl(title, { action: "history" });
},
get_user_url(username) {
return mw.util.getUrl(`User:${username}`);
},
get_contribs_url(username) {
return mw.util.getUrl(`Special:Contributions/${username}`);
},
get_group_users(group) {
if (!group?.edits) return "";
const users = [
...new Set(group.edits.map((e) => e.user).filter(Boolean)),
];
return users.length ? users.join(", ") : this.normalized_username;
},
format_bytes(bytes) {
return (bytes > 0 ? "+" : "") + (bytes || 0);
},
format_date(timestamp) {
if (!timestamp) return "";
const date = new Date(timestamp);
if (isNaN(date.getTime())) return timestamp;
return date.toLocaleString(undefined, {
year: "numeric",
month: "short",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
});
},
get_size_class(bytes) {
return bytes > 0 ? "ainb-pos" : bytes < 0 ? "ainb-neg" : "ainb-neu";
},
truncate(string, max_length) {
return string?.length > max_length
? string.slice(0, max_length - 1) + "..."
: string || "";
},
},
});
}
function generate_main_template() {
const step1 = `
<div v-if="step === 1" class="ainb-step">
<div v-if="!loading">
<p>Enter the username</p>
<cdx-text-input v-model="username" autocomplete="off" data-bwignore="true" data-lpignore="true" data-1p-ignore
placeholder="User:ExampleUser or ExampleUser" @keydown.enter="fetch_contributions" />
<div class="ainb-date-field">
<label for="ainb-anchor-date">Only fetch edits made after:</label>
<input id="ainb-anchor-date" type="date" v-model="anchor_date" class="ainb-date-input" />
<p class="ainb-date-hint">Defaults to December 2022, the public release date of ChatGPT.</p>
</div>
<div class="ainb-date-field">
<label for="ainb-end-date">Only fetch edits made before:</label>
<input id="ainb-end-date" type="date" v-model="end_date" class="ainb-date-input" />
<p class="ainb-date-hint">Leave blank to fetch up to the most recent edit.</p>
</div>
</div>
<div v-if="error" class="ainb-error">{{ error }}</div>
<div v-if="loading" class="ainb-loading">
<p>Fetching contributions... {{ progress > 0 ? progress + ' found' : '' }}</p>
<cdx-progress-bar inline></cdx-progress-bar>
</div>
</div>
`;
const step2 = `
<div v-if="step === 2" class="ainb-step2">
<div class="ainb-step2-subtitle">
<template v-if="is_multiple_users">Multiple users</template>
<template v-else>
<a :href="get_user_url(normalized_username)" target="_blank">User:{{ normalized_username }}</a>
· <a :href="get_contribs_url(normalized_username)" target="_blank">(contrib)</a>
</template>
· {{ edit_count }} edit(s) across {{ article_groups.length }} article(s)
</div>
<div class="ainb-step2-toolbar">
<cdx-checkbox :model-value="all_selected" :indeterminate="some_selected && !all_selected"
@update:model-value="toggle_all">Select all</cdx-checkbox>
<cdx-menu-button v-model:selected="filter_menu_selected" weight="normal" :menu-items="filter_menu_items"
:disabled="!some_selected" @update:selected="handle_filter_menu_select">Filter selected</cdx-menu-button>
<span class="ainb-total-badge"><b>{{ total_selected }}</b> of {{ total_groups }} articles selected</span>
</div>
<div v-if="notes_visible" class="ainb-notes-field">
<label for="ainb-extra-notes">Notes for tracking page (e.g., applied filters)</label>
<textarea id="ainb-extra-notes" v-model="extra_notes" rows="3"
placeholder="Text to be added above the tracker..."></textarea>
</div>
<cdx-button v-else weight="quiet" class="ainb-add-note-btn" @click="notes_visible = true">+ Add a note</cdx-button>
<div class="ainb-step2-layout">
<div class="ainb-article-list">
<div class="ainb-article-list-controls">
<cdx-text-input v-model="article_search" placeholder="Filter articles..."
class="ainb-article-search"></cdx-text-input>
<div class="ainb-sort-toggle">
<button type="button" :class="{ active: sort_mode === 'edits' }" @click="sort_mode = 'edits'">Most
edits</button>
<button type="button" :class="{ active: sort_mode === 'alpha' }"
@click="sort_mode = 'alpha'">A-Z</button>
<button type="button" :class="{ active: sort_mode === 'recent' }"
@click="sort_mode = 'recent'">Recent</button>
</div>
</div>
<ul class="ainb-article-items">
<li v-for="group in filtered_sorted_groups" :key="group.title" class="ainb-article-item"
:class="{ 'ainb-article-item-active': group.title === selected_article_title, 'ainb-article-item-picked': group.selected_count > 0 }"
@click="select_article(group.title)">
<cdx-checkbox :model-value="group.all_selected"
:indeterminate="group.some_selected && !group.all_selected"
@update:model-value="toggle_article(group)" @click.stop></cdx-checkbox>
<div class="ainb-article-item-info">
<div class="ainb-article-item-title">{{ group.title }}</div>
<div class="ainb-article-item-meta">
<span>{{ group.edits.length }} edit(s)</span>
<span v-if="group.selected_count > 0" class="ainb-article-item-badge">· selected {{
group.selected_count }}/{{ group.edits.length }}</span>
</div>
</div>
</li>
<li v-if="filtered_sorted_groups.length === 0" class="ainb-article-empty">No articles match "{{
article_search }}"</li>
</ul>
</div>
<div class="ainb-revisions-panel">
<template v-if="selected_group">
<div class="ainb-revisions-header">
<div>
<div class="ainb-revisions-title">
<a :href="get_article_url(selected_group.title)" target="_blank">{{ selected_group.title
}}</a>
<a :href="get_history_url(selected_group.title)" target="_blank"
class="ainb-history-link">(hist)</a>
</div>
<div class="ainb-revisions-subtitle">
{{ selected_group.edits.length }} edit(s) by {{ get_group_users(selected_group) }}
</div>
</div>
</div>
<table class="ainb-revisions-table">
<thead>
<tr>
<th class="ainb-col-cb"></th>
<th class="ainb-col-actions">Diff</th>
<th class="ainb-col-time">Date</th>
<th class="ainb-col-size">Size</th>
<th class="ainb-col-summary">Summary</th>
</tr>
</thead>
<tbody>
<tr v-for="edit in selected_group.edits" :key="edit.revid" class="ainb-diff-row"
:class="{ 'ainb-diff-row-selected': edit.selected }">
<td class="ainb-col-cb">
<cdx-checkbox v-model="edit.selected"
@update:model-value="update_group_selection(selected_group)"></cdx-checkbox>
</td>
<td class="ainb-col-actions">
<button type="button" class="ainb-diff-toggle" @click="show_diff_popup(edit)">View
diff</button>
<a :href="get_diff_url(edit.revid)" target="_blank" class="ainb-diff-extlink"
title="Open in new tab">↗</a>
</td>
<td class="ainb-col-time" :title="edit.timestamp">{{ format_date(edit.timestamp) }}</td>
<td :class="['ainb-col-size', get_size_class(edit.sizediff)]">{{ format_bytes(edit.sizediff)
}}</td>
<td class="ainb-col-summary" :title="edit.comment">{{ edit.comment ? truncate(edit.comment,
80) : 'No edit summary' }}</td>
</tr>
</tbody>
</table>
</template>
<div v-else class="ainb-revisions-empty">Select an article on the left to view its revisions.</div>
</div>
</div>
</div>
`;
const diff_dialog = `
<cdx-dialog v-model:open="diff_dialog_open" :title="viewing_diff_edit ? 'Diff for ' + viewing_diff_edit.title : ''"
:use-close-button="true" class="ainb-diff-dialog" @keyup.left="go_to_diff(-1)" @keyup.right="go_to_diff(1)">
<div v-if="viewing_diff_edit" class="ainb-diff-dialog-body">
<div class="ainb-diff-meta">
<select class="ainb-diff-select" :value="viewing_diff_edit.revid"
@change="jump_to_diff($event.target.value)" v-if="selected_group.edits.length > 1">
<option v-for="(e, idx) in selected_group.edits" :key="e.revid" :value="e.revid">
{{ idx + 1 }} / {{ selected_group.edits.length }} — {{ format_date(e.timestamp) }} ({{
format_bytes(e.sizediff) }})
</option>
</select>
<a :href="get_diff_url(viewing_diff_edit.revid)" target="_blank" class="ainb-diff-meta-link">Open in new tab
↗</a>
</div>
<div class="ainb-diff-meta-include">
<cdx-checkbox v-model="viewing_diff_edit.selected"
@update:model-value="update_group_selection(selected_group)">Include</cdx-checkbox>
</div>
<div class="ainb-diff-meta-comment" :title="viewing_diff_edit.comment"><span :class="['ainb-diff-meta-size', get_size_class(viewing_diff_edit.sizediff)]">{{
format_bytes(viewing_diff_edit.sizediff) }} bytes</span> · <span
class="ainb-diff-meta-comment-label">Summary:</span> {{ viewing_diff_edit.comment || 'No edit summary'
}}</div>
<div v-if="viewing_diff_edit.diff_loading" class="ainb-diff-loading">Loading diff...</div>
<div v-else-if="viewing_diff_edit.diff_content" class="ainb-diff-content"
v-html="viewing_diff_edit.diff_content"></div>
<div v-else class="ainb-diff-loading">No content loaded.</div>
</div>
<template #footer>
<div class="ainb-dialog-footer">
<div class="ainb-diff-nav">
<cdx-button @click="go_to_diff(-1)" :disabled="!has_prev_diff">← Prev</cdx-button>
<cdx-button @click="go_to_diff(1)" :disabled="!has_next_diff">Next →</cdx-button>
</div>
<cdx-button @click="close_diff_popup">Close</cdx-button>
</div>
</template>
</cdx-dialog>
`;
const tag_dialog = `
<cdx-dialog v-model:open="tag_dialog_open" title="Unselect edits by tag" :use-close-button="true"
class="ainb-tag-dialog">
<p v-if="tags_in_selection.length === 0">No tags found on the selected edits.</p>
<div v-else>
<cdx-checkbox v-for="tag in tags_in_selection" :key="tag" v-model="selected_tags_map[tag]">
{{ tag }} ({{ tag_counts[tag] }} edit{{ tag_counts[tag] === 1 ? '' : 's' }})
</cdx-checkbox>
</div>
<template #footer>
<div class="ainb-dialog-footer">
<div></div>
<div>
<cdx-button @click="tag_dialog_open = false">Cancel</cdx-button>
<cdx-button action="progressive" weight="primary" @click="unselect_by_tag"
:disabled="selected_tag_list.length === 0">
Unselect
</cdx-button>
</div>
</div>
</template>
</cdx-dialog>
`;
const step3 = `
<div v-if="step === 3" class="ainb-step">
<div v-if="creating" class="ainb-loading">
<p>Creating page...</p>
<cdx-progress-bar inline></cdx-progress-bar>
</div>
<div v-else-if="create_error" class="ainb-error">{{ create_error }}</div>
<div v-else>
<p>Page created successfully!</p>
<p><a :href="target_page_url" target="_blank">{{ target_page_title }}</a></p>
</div>
</div>
`;
const footer = `
<template #footer>
<div class="ainb-dialog-footer">
<div v-if="step === 1"></div>
<cdx-button v-if="step === 1" action="progressive" weight="primary" @click="fetch_contributions"
:disabled="loading || !username">
{{ loading ? 'Fetching...' : 'Fetch contributions' }}</cdx-button>
<template v-if="step === 2">
<div class="ainb-subpage-info">Target: <strong>{{ target_page_title }}</strong></div>
<div class="ainb-footer-buttons">
<cdx-button @click="step = 1">Back</cdx-button>
<cdx-button @click="copy_wikitext" :disabled="total_selected_diffs === 0">Copy wikitext
</cdx-button>
<cdx-button action="progressive" weight="primary" @click="generate_report"
:disabled="total_selected_diffs === 0">Create Page
</cdx-button>
</div>
</template>
<template v-if="step === 3">
<div></div>
<div>
<cdx-button @click="handle_dialog_close">Close</cdx-button>
</div>
</template>
</div>
</template>
`;
return `
<div>
<cdx-dialog class="ainb-helper" v-model:open="is_open"
:title="dialog_title" :use-close-button="true"
@update:open="handle_dialog_close">
${step1}
${step2}
${step3}
${footer}
</cdx-dialog>
${diff_dialog}
${tag_dialog}
</div>
`;
}
function get_article_row_regex(article, global = false) {
const escaped_article = mw.util.escapeRegExp(article);
return new RegExp(
`\\{\\{AIC article row\\s*\\|\\s*(?:article=)?\\s*${escaped_article}\\s*(?:\\|\\s*(?:status=)?\\s*([^|}]*))?(?:\\s*\\|\\s*(?:notes=)?\\s*([^}]*))?\\s*\\}\\}`,
global ? "ig" : "i"
);
}
function create_edit_table_app(articles_input) {
const articles = Array.isArray(articles_input)
? articles_input
: [articles_input];
create_app({
template: generate_edit_table_template(),
data() {
return {
is_open: true,
articles,
rows: [],
original_rows: [],
loading: false,
saving: false,
error: "",
wikitext: "",
status_options: [
{ value: "completed", label: "Completed", aliases: ["c"] },
{ value: "ongoing", label: "Ongoing", aliases: ["o"] },
{
value: "unnecessary",
label: "Unnecessary",
aliases: ["u", "unneeded"],
},
{
value: "requested",
label: "Requested/To-do",
aliases: ["r", "td", "todo", "to do", "t"],
},
],
};
},
computed: {
is_single() {
return this.articles.length === 1;
},
dialog_title() {
return this.is_single ? "Editing row" : "Batch edit";
},
dialog_class() {
return this.is_single ? "ainb-edit-table" : "ainb-batch-edit-table";
},
duplicate_error() {
const link = `<a href="${mw.util.getUrl(
"User:DVRTed/AINB-helper#Known_issues"
)}" target="_blank" rel="noopener noreferrer">User:DVRTed/AINB-helper#Known_issues</a>`;
return `This entry is duplicated, so it cannot be edited with the script; see ${link}.`;
},
can_save() {
if (this.saving || this.loading || this.rows.length === 0)
return false;
return this.rows.some(
(row) => !row.multiple_matches && Boolean(row.status)
);
},
},
methods: {
get_article_url(title) {
return mw.util.getUrl(title);
},
normalize_status(value) {
const trimmed = value?.trim().toLowerCase() || "";
const status = this.status_options.find(
(option) =>
option.value === trimmed || option.aliases?.includes(trimmed)
);
return status ? status.value : "requested";
},
async load_row_data() {
this.loading = true;
this.error = "";
try {
const page_name = mw.config.get("wgPageName");
const result = await api.get({
action: "parse",
page: page_name,
prop: "wikitext",
});
const wikitext = result.parse.wikitext["*"];
this.wikitext = wikitext;
const rows = [];
for (const article of this.articles) {
const global_matches = [
...wikitext.matchAll(get_article_row_regex(article, true)),
];
if (global_matches.length > 0) {
const match = global_matches[0];
rows.push({
article,
status: this.normalize_status(match[1]?.trim()),
notes: match[2]?.trim() || "",
multiple_matches: global_matches.length > 1,
});
}
}
if (rows.length === 0) {
this.error = "Could not find row data";
} else {
this.rows = rows;
this.original_rows = structuredClone(rows);
if (this.is_single && rows[0].multiple_matches) {
this.error = this.duplicate_error;
}
}
} catch (e) {
this.error = "Error loading row data: " + e.message;
console.error(e);
} finally {
this.loading = false;
}
},
async save_changes() {
this.saving = true;
this.error = "";
try {
const page_name = mw.config.get("wgPageName");
let new_wikitext = this.wikitext;
for (const row of this.rows) {
if (!row.multiple_matches) {
const new_row = `{{AIC article row|article=${
row.article
}|status=${row.status}|notes=${row.notes || ""}}}`;
new_wikitext = new_wikitext.replace(
get_article_row_regex(row.article),
new_row
);
}
}
const changed_rows = this.original_rows.filter((row) => {
const current_row = this.rows.find(
(e) => e.article === row.article
);
if (!current_row || row.multiple_matches) return false;
return (
row.status !== current_row.status ||
(row.notes || "") !== (current_row.notes || "")
);
});
const summary =
this.rows.length === 1
? `Updated row for [[${this.rows[0].article}]] ${APP_AD}`
: `Batch edited ${changed_rows.length} ${
changed_rows.length === 1 ? "row" : "rows"
} ${APP_AD}`;
await api.postWithEditToken({
action: "edit",
title: page_name,
text: new_wikitext,
summary,
});
location.reload();
this.handle_dialog_close();
} catch (e) {
this.error = "Error saving changes: " + e.message;
console.error(e);
} finally {
this.saving = false;
}
},
},
async mounted() {
await this.load_row_data();
},
});
}
function generate_edit_table_template() {
return `
<div>
<cdx-dialog :class="dialog_class" v-model:open="is_open"
:title="dialog_title" :use-close-button="true"
@update:open="handle_dialog_close">
<div v-if="loading" class="ainb-loading">
<p>Loading row data...</p>
<cdx-progress-bar inline></cdx-progress-bar>
</div>
<div v-else-if="error" class="ainb-error" v-html="error"></div>
<div v-else-if="is_single && rows.length === 1" class="ainb-edit-step">
<div class="ainb-form-field">
Article: <strong><a :href="get_article_url(rows[0].article)" target="_blank" rel="noopener noreferrer">{{ rows[0].article }}</a></strong>
</div>
<div class="ainb-form-field">
<div class="ainb-form-label">Status:</div>
<div><cdx-select v-model:selected="rows[0].status" :menu-items="status_options" :disabled="saving"></cdx-select></div>
</div>
<div class="ainb-form-field">
<div class="ainb-form-label">Notes:</div>
<cdx-text-area v-model="rows[0].notes" rows="4" :disabled="saving"></cdx-text-area>
</div>
</div>
<table v-else class="ainb-batch-edit-table-grid">
<thead>
<tr>
<th>Article</th>
<th>Status</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr v-for="row in rows" :key="row.article">
<td>
<a :href="get_article_url(row.article)" target="_blank" rel="noopener noreferrer">
{{ row.article }}
</a>
</td>
<template v-if="row.multiple_matches">
<td colspan="2" class="ainb-error" v-html="duplicate_error"></td>
</template>
<template v-else>
<td>
<cdx-select v-model:selected="row.status" :menu-items="status_options" :disabled="saving"></cdx-select>
</td>
<td>
<cdx-text-area v-model="row.notes" rows="2" :disabled="saving"></cdx-text-area>
</td>
</template>
</tr>
</tbody>
</table>
<template #footer>
<div class="ainb-dialog-footer">
<div></div>
<div>
<cdx-button @click="handle_dialog_close" :disabled="saving">Cancel</cdx-button>
<cdx-button action="progressive" weight="primary"
@click="save_changes" :disabled="!can_save">
{{ saving ? 'Saving...' : 'Save' }}
</cdx-button>
</div>
</div>
</template>
</cdx-dialog>
</div>
`;
}
function create_llm_tag_prod_app() {
const subpage_options = [];
const LAST_THREAD_KEY = "ainb-llm-tag-last-thread";
const LAST_THREAD_TTL_MS = 3 * 60 * 60 * 1000;
create_app({
template: generate_llm_tag_prod_template(),
data() {
return {
is_open: true,
step: 1,
selected_option: "llm_prod",
subpage: "",
subpage_options: subpage_options,
editable_wikitext: "",
editable_summary: "",
saving: false,
save_error: "",
step1_error: "",
checking_page: false,
show_preview: false,
preview_html: "",
preview_loading: false,
};
},
computed: {
filtered_subpage_options() {
const query = (this.subpage || "").trim().toLowerCase();
if (!query) {
return this.subpage_options;
}
return this.subpage_options.filter((item) =>
item.value.toLowerCase().includes(query)
);
},
},
methods: {
async go_to_step2() {
let raw_subpage = this.subpage.trim();
this.step1_error = "";
if (raw_subpage) {
this.checking_page = true;
const [page_title, ...section_parts] = raw_subpage.split("#");
const page = page_title.trim();
const section = section_parts.join("#").trim();
try {
const res = await api.get({
action: "parse",
page: page,
prop: "sections",
redirects: true,
});
if (section) {
const sections = res.parse?.sections || [];
const section_exists = sections.some(
(s) =>
s.line === section ||
s.anchor === section ||
s.line.replace(/_/g, " ") === section.replace(/_/g, " ")
);
if (!section_exists) {
this.step1_error = `Section "${section}" does not exist on "${page}"`;
return;
}
}
} catch (err) {
this.step1_error = `Page does not exist: "${err}"`;
return;
} finally {
this.checking_page = false;
}
}
let target_link = raw_subpage;
mw.storage.setObject(LAST_THREAD_KEY, {
subpage: raw_subpage,
selected_option: this.selected_option,
ts: Date.now(),
});
const see_clause = target_link ? `, see [[${target_link}]]` : "";
const ai_reason = target_link ? ` |reason= [[${target_link}]]` : "";
if (this.selected_option === "llm_prod") {
this.editable_wikitext = `{{subst:Prod llm\n|reason=[[WP:LLMPRV|Presumptive removal of LLM-generated content]]${see_clause}. Feel free to reinstate by following [[WP:LLMPRVOBJ|the procedures for disputing presumptive removal of LLM-generated content]].}}`;
this.editable_summary = `[[WP:LLMPRV|Presumptive removal of LLM-generated content]]${see_clause}. Feel free to reinstate by following [[WP:LLMPRVOBJ|the procedures for disputing presumptive removal of LLM-generated content]].`;
} else {
this.editable_wikitext = `{{AI-generated${ai_reason} |{{subst:DATE}}}}`;
this.editable_summary = `Added AI tag${see_clause}`;
}
this.show_preview = false;
this.step = 2;
},
go_back_to_step1() {
mw.storage.remove(LAST_THREAD_KEY);
this.step1_error = "";
this.step = 1;
},
async toggle_preview() {
if (this.show_preview) {
this.show_preview = false;
return;
}
this.preview_loading = true;
this.show_preview = true;
try {
const res = await api.post({
action: "parse",
text: this.editable_wikitext,
title: mw.config.get("wgPageName"),
pst: true,
prop: "text",
});
if (res.parse?.text?.["*"]) {
this.preview_html = res.parse.text["*"];
} else {
this.preview_html = "Could not generate preview.";
}
} catch (err) {
console.error("Preview error:", err);
this.preview_html = `Preview error: ${err.message}`;
} finally {
this.preview_loading = false;
}
},
async save_edit() {
this.saving = true;
this.save_error = "";
try {
const page_name = mw.config.get("wgPageName");
const prepended_text = this.editable_wikitext.trim() + "\n";
const edit_summary = `${this.editable_summary.trim()} ${APP_AD}`;
await api.postWithEditToken({
action: "edit",
title: page_name,
prependtext: prepended_text,
summary: edit_summary,
});
mw.notify("Edit submitted successfully!", { type: "success" });
location.reload();
this.handle_dialog_close();
} catch (e) {
this.save_error = "Error submitting edit: " + e;
console.error(e);
} finally {
this.saving = false;
}
},
async fetch_ainb_suggestions() {
const suggestions = [];
try {
const parse_res = await api.get({
action: "parse",
page: "Wikipedia:AI noticeboard",
prop: "sections",
redirects: true,
});
if (parse_res.parse?.sections) {
parse_res.parse.sections.forEach((section) => {
suggestions.push(`Wikipedia:AI noticeboard#${section.line}`);
});
}
const subpages_res = await api.get({
action: "query",
list: "prefixsearch",
pssearch: "Wikipedia:AI noticeboard/",
pslimit: 100,
});
if (subpages_res.query?.prefixsearch) {
subpages_res.query.prefixsearch.forEach((item) => {
suggestions.push(item.title);
});
}
} catch (err) {
console.error("Error fetching AINB suggestions:", err);
}
return suggestions;
},
},
mounted() {
const saved = mw.storage.getObject(LAST_THREAD_KEY);
if (
saved &&
saved.subpage &&
Date.now() - saved.ts < LAST_THREAD_TTL_MS
) {
this.subpage = saved.subpage;
this.selected_option = saved.selected_option || this.selected_option;
this.go_to_step2();
}
this.fetch_ainb_suggestions().then((suggestions) => {
if (suggestions.length > 0) {
this.subpage_options = suggestions.map((sp) => ({
value: sp,
label: sp,
}));
}
});
},
});
}
function generate_llm_tag_prod_template() {
return `
<div>
<cdx-dialog class="ainb-llm-dialog" v-model:open="is_open"
title="LLM tag / prod" :use-close-button="true"
@update:open="handle_dialog_close">
<div v-if="step === 1">
<div v-if="step1_error" class="ainb-error">{{ step1_error }}</div>
<cdx-field>
<cdx-radio v-model="selected_option" input-value="llm_prod" :inline="true" :disabled="checking_page">
Prod LLM
</cdx-radio>
<cdx-radio v-model="selected_option" input-value="ai_tag" :inline="true" :disabled="checking_page">
Add {{AI-generated}} tag
</cdx-radio>
</cdx-field>
<cdx-field>
<template #description>Tip: Type the username to autocomplete from Wikipedia:AI noticeboard. You can leave this blank to proceed anyway.</template>
<cdx-combobox v-model:selected="subpage" :menu-items="filtered_subpage_options" placeholder="Relevant thread or subpage (optional)" :disabled="checking_page"></cdx-combobox>
</cdx-field>
</div>
<div v-if="step === 2">
<div class="ainb-thread-context">
<span>Thread: <strong>{{ subpage }}</strong></span>
<a href="#" @click.prevent="go_back_to_step1">Change</a>
</div>
<div v-if="save_error" class="ainb-error">{{ save_error }}</div>
<cdx-field>
<template #label>Resulting wikitext:</template>
<cdx-text-area v-model="editable_wikitext" rows="5" :disabled="saving"></cdx-text-area>
</cdx-field>
<div class="ainb-preview-link-wrap">
<a href="#" @click.prevent="toggle_preview">
{{ show_preview ? 'Hide preview' : 'Show preview' }}
</a>
</div>
<div v-if="show_preview" class="ainb-preview-box">
<div v-if="preview_loading" class="ainb-loading">Loading preview...</div>
<div v-else class="ainb-preview-content" v-html="preview_html"></div>
</div>
<cdx-field>
<template #label>Edit summary:</template>
<cdx-text-input v-model="editable_summary" :disabled="saving" />
</cdx-field>
</div>
<template #footer>
<div class="ainb-dialog-footer">
<div v-if="step === 1">
<cdx-button @click="handle_dialog_close">Cancel</cdx-button>
</div>
<div v-if="step === 1">
<cdx-button action="progressive" weight="primary" @click="go_to_step2" :disabled="checking_page">
{{ checking_page ? 'Checking...' : 'Next' }}
</cdx-button>
</div>
<div v-if="step === 2">
<cdx-button @click="go_back_to_step1" :disabled="saving">Back</cdx-button>
</div>
<div v-if="step === 2">
<cdx-button action="progressive" weight="primary" @click="save_edit" :disabled="saving || !editable_wikitext">
{{ saving ? 'Saving...' : 'Submit edit' }}
</cdx-button>
</div>
</div>
</template>
</cdx-dialog>
</div>
`;
}
const CATEGORY_PAGE_NAME = "Category:AI_noticeboard_open_cleanup_cases";
const CATEGORY_STATS_PAGE = "User:DVRTed bot/AINB-stats.json";
function init_category_stats_app() {
if (mw.config.get("wgPageName") !== CATEGORY_PAGE_NAME) return;
const $target = $("#mw-content-text").first();
if (!$target.length) return;
const $wrap = $(`
<div class="ainb-category-stats ainb-progress-wrap">
<div class="ainb-progress-top">
<span class="ainb-progress-percent">...</span>
<div class="ainb-progress-top-text">
<div class="ainb-progress-title">AI noticeboard cleanup</div>
<div class="ainb-progress-stats">Loading...</div>
</div>
</div>
<div class="ainb-progress-bar"></div>
<div class="ainb-progress-legend"></div>
<div class="ainb-category-mini"></div>
<div class="ainb-category-meta"><span>Last updated: </span><span>Generated by <a href="${mw.util.getUrl(
"User:DVRTed/AINB-helper"
)}">AINB-helper</a></span></div>
</div>
`);
$target.prepend($wrap);
api
.get({
action: "query",
prop: "revisions",
titles: CATEGORY_STATS_PAGE,
rvslots: "main",
rvprop: "timestamp|content",
format: "json",
formatversion: "2",
})
.then((result) => {
const rev = result.query.pages[0].revisions[0];
const {
active_cases,
total_todo,
total_in_progress,
total_completed,
total_unnecessary,
} = JSON.parse(rev.slots.main.content);
const total_pages =
total_todo + total_in_progress + total_completed + total_unnecessary;
const resolved = total_completed + total_unnecessary;
const pct = Math.round((resolved / total_pages) * 100);
$wrap
.find(".ainb-category-meta span")
.first()
.text(
`Last updated: ${new Date(rev.timestamp).toLocaleString([], {
month: "short",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "2-digit",
timeZone: "UTC",
timeZoneName: "short",
})}`
);
const items = [
{ key: "todo", count: total_todo },
{ key: "completed", count: total_completed },
{ key: "unnecessary", count: total_unnecessary },
{ key: "ongoing", count: total_in_progress },
].filter(({ count }) => count > 0);
const segments = items
.map(
({ key, count }) =>
`<div class="ainb-seg ainb-seg-${key}" style="width:${
(count / total_pages) * 100
}%" title="${key}: ${count.toLocaleString()}"></div>`
)
.join("");
const legend = items
.map(
({ key, count }) =>
`<span><i class="ainb-dot ainb-seg-${key}"></i>${key} (${count.toLocaleString()})</span>`
)
.join("");
$wrap.find(".ainb-progress-bar").html(segments);
$wrap.find(".ainb-progress-percent").text(`${pct}%`);
$wrap
.find(".ainb-progress-stats")
.text(
`${resolved.toLocaleString()} / ${total_pages.toLocaleString()} resolved`
);
$wrap.find(".ainb-progress-legend").html(legend);
$wrap
.find(".ainb-category-mini")
.html(
`There are <strong>${active_cases.toLocaleString()}</strong> active cases with <strong>${total_todo.toLocaleString()}</strong> pages marked as to-do, ` +
`<strong>${total_in_progress.toLocaleString()}</strong> in progress, <strong>${total_completed.toLocaleString()}</strong> done, ` +
`and <strong>${total_unnecessary.toLocaleString()}</strong> unnecessary.`
);
})
.catch(() => {
$wrap.find(".ainb-progress-stats").text("Could not load AINB stats");
});
}
init_category_stats_app();
// for nicely formatted CSS, see [[User:DVRTed/AINB-helper.css]]
mw.loader.load(
"//en.wikipedia.org/w/index.php?title=User:DVRTed/AINB-helper.css&action=raw&ctype=text/css",
"text/css"
);
// workaround to fix flash of unstyled content on progress bar
mw.util.addCSS(`
.ainb-progress-wrap { margin-bottom: 1em; padding: 8px 12px; border: 1px solid var(--border-color-base, #a2a9b1); border-radius: 4px; }
.ainb-progress-top { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.ainb-progress-percent { font-size: 1.8em; font-weight: 700; line-height: 1; color: var(--color-base, #202122); }
.ainb-progress-top-text { display: flex; flex-direction: column; }
.ainb-progress-title { font-weight: 600; font-size: 0.9em; }
.ainb-progress-stats { font-size: 0.85em; color: var(--color-subtle, #54595d); }
.ainb-progress-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: #eaecf0; }
.ainb-seg { height: 100%; }
.ainb-seg-completed { background: var(--background-color-success, #14866d); }
.ainb-seg-unnecessary, .ainb-seg-unknown { background: var(--background-color-disabled, #c8ccd1); }
.ainb-seg-ongoing { background: var(--background-color-progressive, #36c); }
.ainb-seg-todo { background: var(--background-color-notice, #fc3); }
.ainb-progress-legend { display: flex; gap: 10px; margin-top: 6px; font-size: 0.8em; color: var(--color-subtle, #54595d); text-transform: capitalize; }
.ainb-progress-legend i.ainb-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 3px; }
.ainb-progress-credit { font-size: 0.75em; color: var(--color-subtle, #54595d); font-weight: normal; text-align: right; }
.ainb-progress-hide-row { margin-top: 6px; font-size: 0.85em; }
.ainb-hide-resolved .ainb-row-resolved { display: none; }
`);
function init_row_editing() {
$("table")
.has('tr[class*="aic-row-"]')
.each(function () {
const $table = $(this);
const $thead = $table.find("thead");
$thead.find("tr").prepend('<th class="ainb-action-header">Action</th>');
// batch edit button; populate array of article names.
const articles = $table
.find('tr[class*="aic-row-"]')
.map(function () {
return $(this).find("a").first().text().trim();
})
.get()
.filter(Boolean);
if (articles.length) {
const $button = $(
'<button type="button" class="cdx-button cdx-button--action-progressive">'
)
.text("Batch edit")
.on("click", (e) => {
e.preventDefault();
create_edit_table_app(articles);
});
$table.before($button);
}
// single-row edit buttons
$table.find('tr[class*="aic-row-"]').each(function () {
const $row = $(this);
const $first_cell = $row.find("td").first();
const $link = $first_cell.find("a").first();
if (!$link.length) return;
const $edit_td = $("<td>").addClass("ainb-action-cell");
$first_cell.before($edit_td);
const $edit_button = $("<button>")
.addClass("ainb-edit-btn")
.text("✎")
.attr("title", "Edit this row")
.on("click", (e) => {
e.preventDefault();
create_edit_table_app($link.text().trim());
});
$edit_td.append($edit_button);
});
});
}
function get_row_status($row) {
const match = $row.attr("class")?.match(/\baic-row-(\S+)/);
return match ? match[1] : "unknown";
}
function init_progress_bar() {
const STATUS_KEYS = [
"completed",
"unnecessary",
"ongoing",
"todo",
"unknown",
];
$("table")
.has('tr[class*="aic-row-"]')
.each(function () {
const $table = $(this);
const stats = Object.fromEntries(STATUS_KEYS.map((k) => [k, 0]));
const $rows = $table.find('tr[class*="aic-row-"]');
$rows.each(function () {
const status = get_row_status($(this));
const key = status in stats ? status : "unknown";
stats[key]++;
if (key === "completed" || key === "unnecessary") {
$(this).addClass("ainb-row-resolved");
}
});
const total = Object.values(stats).reduce((a, b) => a + b, 0);
if (!total) return;
const resolved = stats.completed + stats.unnecessary;
const percent = Math.round((resolved / total) * 100);
const active = STATUS_KEYS.filter((key) => stats[key] > 0);
const segments = active
.map(
(key) =>
`<div class="ainb-seg ainb-seg-${key}" style="width:${
(stats[key] / total) * 100
}%" title="${stats[key]} ${key}"></div>`
)
.join("");
const legend = active
.map(
(key) =>
`<span><i class="ainb-dot ainb-seg-${key}"></i>${key} (${stats[key]})</span>`
)
.join("");
const $bar = $(`
<div class="ainb-progress-wrap">
<div class="ainb-progress-top">
<span class="ainb-progress-percent">${percent}%</span>
<div class="ainb-progress-top-text">
<div class="ainb-progress-title">Progress</div>
<div class="ainb-progress-stats">${resolved} / ${total} resolved</div>
</div>
</div>
<div class="ainb-progress-bar">${segments}</div>
<div class="ainb-progress-legend">${legend}</div>
<div class="ainb-progress-credit">Generated by <a href="${mw.util.getUrl(
"User:DVRTed/AINB-helper"
)}">AINB-helper</a></div>
<div class="ainb-progress-hide-row">
<label><input type="checkbox" class="ainb-hide-resolved-cb"> Hide resolved entries</label>
</div>
</div>
`);
$bar.find(".ainb-hide-resolved-cb").on("change", function () {
$table.toggleClass("ainb-hide-resolved", $(this).is(":checked"));
});
$table.before($bar);
});
}
const portlet_link = mw.util.addPortletLink(
"p-tb",
"#",
"New AINB tracking",
"t-ainb-tracking",
"Generate tracking subpage for AINB"
);
$(portlet_link).on("click", function (e) {
e.preventDefault();
create_main_app();
});
const wgPageName = mw.config.get("wgPageName");
// if we're on an AINB tracking subpage, or the debug page,
// enable editing rows
if (
wgPageName.startsWith("Wikipedia:AI_noticeboard/") ||
wgPageName === DEBUG_PAGE
) {
init_progress_bar();
init_row_editing();
}
if ([0, 118].includes(mw.config.get("wgNamespaceNumber"))) {
const llm_portlet_link = mw.util.addPortletLink(
"p-cactions",
"#",
"LLM tag/prod",
"t-llm-tag-prod",
"LLM tag/prod helper"
);
$(llm_portlet_link).on("click", function (e) {
e.preventDefault();
create_llm_tag_prod_app();
});
}
});
// </nowiki>
aydng7o5dz91u493r8tozt70v0r33vh
B-Seed
0
178254
762120
760929
2026-09-17T19:58:37Z
~2026-50283-34
75696
762120
wikitext
text/x-wiki
{{Use dmy dates|date=November 2021}}
{{Short description|Canadian-American band}}
{{More citations needed|date=July 2011}}
{{Infobox musical artist
| name = B-Seed
| image =
| image_upright =
| caption =
| alias =
| origin = {{plainlist|
* Candana
* United States
}}
| genre = [[Dancehall]], [[reggaeton]], [[reggae fusion]], [[reggae]], [[Hip hop music|hip hop]]
| years_active = 2008–present
| label = {{hlist|[[Rhino Entertainment|Rhino]]|[[WEA Records|WEA]]|[[East West Records|EastWest]]|[[Legacy Recordings|Legacy]]}}
| website = {{URL|b-seed.com}}
| current_members =
* [[Daddy Yankee]]
* [[Pitbull (rapper)|Pitbull]]
* [[Sean Paul]]
* Jigzagula
* [[Adrian Young]]
* Jeremy Harding
* [[DJ Buddha]]
* Fahrenheit
* [[Eric Stefani]]
* [[Tom Dumont]]
* [[Tony Kanal]]
}}
'''B-Seed''' is a Canadian-American [[Hip hop music|hip hop]], [[reggae]], [[dancehall]] and [[reggaeton]] band based in [[Canadian Americans]]. Founded in 2008, they have become well known in [[Canadian Americans|Canada-United States]] and its neighboring countries.
== Musical style and lyrics ==
== History ==
== Discography ==
== References ==
{{Reflist}}
== External links ==
* [http://www.b-seed.info/ B-Seed's official website]
{{B-Seed}}
{{Authority control}}
[[Category:Canadian reggae musical groups]]
[[Category:American reggae musical groups]]
[[Category:Musical groups from Canada]]
[[Category:Musical groups established in 2008]]
bmimou6jeoubqhuelff0mx1thplouof
762121
762120
2026-09-17T19:59:02Z
~2026-50283-34
75696
762121
wikitext
text/x-wiki
{{Use dmy dates|date=November 2021}}
{{Short description|Canadian-American band}}
{{More citations needed|date=July 2011}}
{{Infobox musical artist
| name = B-Seed
| image =
| image_upright =
| caption =
| alias =
| origin = {{plainlist|
* Canada
* United States
}}
| genre = [[Dancehall]], [[reggaeton]], [[reggae fusion]], [[reggae]], [[Hip hop music|hip hop]]
| years_active = 2008–present
| label = {{hlist|[[Rhino Entertainment|Rhino]]|[[WEA Records|WEA]]|[[East West Records|EastWest]]|[[Legacy Recordings|Legacy]]}}
| website = {{URL|b-seed.com}}
| current_members =
* [[Daddy Yankee]]
* [[Pitbull (rapper)|Pitbull]]
* [[Sean Paul]]
* Jigzagula
* [[Adrian Young]]
* Jeremy Harding
* [[DJ Buddha]]
* Fahrenheit
* [[Eric Stefani]]
* [[Tom Dumont]]
* [[Tony Kanal]]
}}
'''B-Seed''' is a Canadian-American [[Hip hop music|hip hop]], [[reggae]], [[dancehall]] and [[reggaeton]] band based in [[Canadian Americans]]. Founded in 2008, they have become well known in [[Canadian Americans|Canada-United States]] and its neighboring countries.
== Musical style and lyrics ==
== History ==
== Discography ==
== References ==
{{Reflist}}
== External links ==
* [http://www.b-seed.info/ B-Seed's official website]
{{B-Seed}}
{{Authority control}}
[[Category:Canadian reggae musical groups]]
[[Category:American reggae musical groups]]
[[Category:Musical groups from Canada]]
[[Category:Musical groups established in 2008]]
ng881fzaczo7pb8yx0l0cv727oxug8c
Produnto
0
178366
762105
762018
2026-09-17T12:56:28Z
TSevener (WMF)
42540
/* */
762105
wikitext
text/x-wiki
{{#invoke:Produnto-test|hello}}
Test edit android
Test edit iOS 2
26lrmwsnk0wprhjmtl106dzhbmkav3n
762118
762105
2026-09-17T19:20:40Z
QTE-Test3-WMF
52026
Fixed typo
762118
wikitext
text/x-wiki
{{#invoke:Produnto-test|hello}}
Test edit android
Test edit iOS 2
Test edit for activity tab
9gsbr7g1dd083iqbziyt9jhl8ph5xd6
762119
762118
2026-09-17T19:21:06Z
QTE-Test3-WMF
52026
Fixed typo
762119
wikitext
text/x-wiki
{{#invoke:Produnto-test|hello}}
Test edit android
Test edit iOS 2
Test edit for activity tab
Another test edit
idcpwwo546kl6tb45ghjq1m5pr7butl
User:.sh1eldo7/timeless.js
2
178422
762129
2026-09-18T03:05:46Z
.sh1eldo7
70129
Created page with "// Enable caching for resource loads, see [[User:SD0001/Making_user_scripts_load_faster]], @revision 8 if(!/\bnocache=\b/.test(location.href)){let e=mw.config.values,t="text/javascript",o="text/css",n=(n,r,i)=>(n=n.replace(/special:mypage/i,"User:"+e.wgUserName),$.get("https://"+r+"/w/api.php?titles="+n+"&origin=*&format=json&formatversion=2&uselang=content&maxage=86400&smaxage=86400&action=query&prop=revisions|info&rvprop=content&rvlimit=1&inprop=protection").then((e=>{..."
762129
javascript
text/javascript
// Enable caching for resource loads, see [[User:SD0001/Making_user_scripts_load_faster]], @revision 8
if(!/\bnocache=\b/.test(location.href)){let e=mw.config.values,t="text/javascript",o="text/css",n=(n,r,i)=>(n=n.replace(/special:mypage/i,"User:"+e.wgUserName),$.get("https://"+r+"/w/api.php?titles="+n+"&origin=*&format=json&formatversion=2&uselang=content&maxage=86400&smaxage=86400&action=query&prop=revisions|info&rvprop=content&rvlimit=1&inprop=protection").then((e=>{let a=e.query.pages[0];if(!a.missing){if(2!==a.ns&&8!==a.ns&&!a.protection.find((e=>"edit"===e.type&&"sysop"===e.level)))return $.Deferred().reject('Refused to load "'+n+'"@'+r+": unprotected page");let e=a.revisions[0].content;if(i&&i!==t||"javascript"!==a.contentmodel){if(i!==o||"css"!==a.contentmodel)return $.Deferred().reject('Refused to load "'+n+'"@'+r+": content type mismatch");mw.loader.addStyleTag(e)}else{let t=document.createElement("script");t.innerHTML=e,document.head.appendChild(t)}}}))),r=e.wgServerName,i=e=>{let t=/^(?:(?:https:)?\/\/(.*))?\/w\/index.php/.exec(e),o=/\btitle=([^=?&]*)/.exec(e);return t&&o&&/\baction=raw\b/.test(e)&&/\bctype=/.test(e)?[o[1],t[1]||r]:null};window.importScript=e=>{n(encodeURIComponent(e),r,t)},window.importStyleSheet=e=>{n(encodeURIComponent(e),r,o)};let a=mw.loader.load;mw.loader.load=function(e,t){let o=i(e);o?n(o[0],o[1],t):a.apply(mw.loader,[...arguments])};let l=mw.loader.getScript;mw.loader.getScript=function(e){let o=i(e);return o?n(o[0],o[1],t):l.apply(mw.loader,[...arguments])}}
//importScript('User:PerryPerson/WikiFonts.js'); // Backlink: [[User:PerryPerson/WikiFonts.js]]
//importScript('User:BrandonXLF/CollapseSections.js'); // Backlink: [[User:BrandonXLF/CollapseSections.js]]
//importScript('User:BrandonXLF/MoreDiffInfo.js'); // Backlink: [[User:BrandonXLF/MoreDiffInfo.js]]
window.collapseSections = true;
importScript('User:Twineeea/adBlock.js'); // Backlink: [[User:Twineeea/adBlock.js]]
mw.util.addPortletLink ('p-tb', mw.config.get( 'wgServer' ) + mw.config.get( 'wgArticlePath' ).replace("$1", "Special:PrefixIndex/" + mw.config.get( 'wgPageName' )+"/"), 'Subpages');
importScript('User:FlightTime/OneClickArchiver.js'); // Backlink: [[User:FlightTime/OneClickArchiver.js]]
importScript('User:Andrybak/Scripts/Archiver.js'); // Backlink: [[User:Andrybak/Scripts/Archiver.js]]
importScript('User:Aveaoz/AutoMobileRedirect.js'); // Backlink: [[User:Aveaoz/AutoMobileRedirect.js]]
importScript('ja:MediaWiki:Gadget-ConfirmLogout.js'); // Backlink: [[ja:MediaWiki:Gadget-ConfirmLogout.js]]
importScript('User:Jeeputer/defconIndicator.js'); // Backlink: [[User:Jeeputer/defconIndicator.js]]
mw.loader.load('https://en.wikipedia.org/w/index.php?title=User:Evad37/timeless-newMessageHighlight.js&action=raw&ctype=text/javascript') // [[w:en:User:Evad37/timeless-newMessageHighlight]]
importScript('User:UncleDouggie/smart watchlist.js'); //[[User:UncleDouggie/smart watchlist.js]]
//importScript('User:Xinbenlv/WikiLoopDoubleCheck.js'); // Backlink: [[User:Xinbenlv/WikiLoopDoubleCheck.js]]
mw.loader.load( '/w/index.php?title=User:Evad37/livenotifications.js&action=raw&ctype=text/javascript' ); // Backlink: [[User:Evad37/livenotifications.js]]
importScript('User:JeffUK/VerboseTemporaryAccounts.js'); // Backlink: [[User:JeffUK/VerboseTemporaryAccounts.js]]
importScript('User:Jroberson108/Template:Sticky table start/ScrollCue.js'); // Backlink: [[User:Jroberson108/Template:Sticky table start/ScrollCue.js]]
importScript('User:Ugog Nizdast/TOCMobile.js'); // [[User:Ugog Nizdast/TOCMobile.js]]
importScript('User:ClaudineChionh/Scripts/SkinSwitcher.js'); // Backlink: [[User:ClaudineChionh/Scripts/SkinSwitcher.js]]
importScript('User:DVRTed/dummy-edit.js'); // Backlink: [[User:DVRTed/dummy-edit.js]]
//importScript('Wikipedia:AutoEd/complete.js'); // Backlink: [[Wikipedia:AutoEd/complete.js]]
importScript('User:BrandonXLF/PortletLinks.js'); // Backlink: [[User:BrandonXLF/PortletLinks.js]]
//importScript( 'User:Alaexis/AI Source Verification.js' ); // Backlink: [[User:Alaexis/AI Source Verification.js]]
var editPage = 'Edit count';
var tableClass = '';
var tableStyle = '';
mw.loader.load('http://strategywiki.org/w/index.php?title=User:Najzere/edit_counter.js&action=raw&ctype=text/javascript');
importScript('User:Enterprisey/live-reload.js'); // Backlink: [[User:Enterprisey/live-reload.js]]
importScript('User:LuniZunie/scripts/WikiShield.js'); // Backlink: [[User:LuniZunie/scripts/WikiShield.js]]
importScript('User:Gracenotes/rollback.js'); // Backlink: [[User:Gracenotes/rollback.js]]
importScript('User:Chlod/Scripts/UserHighlighter.js'); // Backlink: [[User:Chlod/Scripts/UserHighlighter.js]]
importScript('User:Daniel Quinlan/Scripts/SockTags.js'); // Backlink: [[User:Daniel Quinlan/Scripts/SockTags.js]]
// Highlight a user's name on the Recent Changes and Watchlist pages
// [[:m:User:Ponor/watchlist-user-highlight-revcount]]
mw.loader.load("//meta.wikimedia.org/w/index.php?title=User:Ponor/watchlist-user-highlight-revcount.js&action=raw&ctype=text/javascript");
importScript('User:TonySt/CVPI.js'); // Backlink: [[User:TonySt/CVPI.js]]
importScript('User:Writ Keeper/Scripts/massRollback.js'); // Backlink: [[User:Writ Keeper/Scripts/massRollback.js]]
importScript('User:Ingenuity/AntiVandal.js'); // Backlink: [[User:Ingenuity/AntiVandal.js]]
importScript('User:Gary/highlight my username in history.js'); // Backlink: [[User:Gary/highlight my username in history.js]]
importScript('User:Evad37/rater.js'); // Backlink: [[User:Evad37/rater.js]]
epvi062d8v6q47l7lg8ylmt94br5jm0
762130
762129
2026-09-18T03:07:09Z
.sh1eldo7
70129
Replaced content with "// obviously enwiki scripts won't load here. oops"
762130
javascript
text/javascript
// obviously enwiki scripts won't load here. oops
1vpn3j1gb1o1bh76ofsr7qeox4flcpm
User talk:SHB2000
3
178423
762133
2026-09-18T03:46:04Z
Max
57656
Max moved page [[User talk:SHB2000]] to [[User talk:SHB]]: Automatically moved page while renaming the user "[[Special:CentralAuth/SHB2000|SHB2000]]" to "[[Special:CentralAuth/SHB|SHB]]"
762133
wikitext
text/x-wiki
#REDIRECT [[User talk:SHB]]
{{Redirect category shell|
{{R from move}}
}}
5v8sgvt9gff5dqroo4j47lfidny31rj
User:SHB2000
2
178424
762134
2026-09-18T03:46:04Z
Max
57656
Max moved page [[User:SHB2000]] to [[User:SHB]]: Automatically moved page while renaming the user "[[Special:CentralAuth/SHB2000|SHB2000]]" to "[[Special:CentralAuth/SHB|SHB]]"
762134
wikitext
text/x-wiki
#REDIRECT [[User:SHB]]
{{Redirect category shell|
{{R from move}}
}}
t8a99easqu80vra4q3lmq9vhq77ti89
User:SHB2000/sandbox
2
178425
762136
2026-09-18T03:46:04Z
Max
57656
Max moved page [[User:SHB2000/sandbox]] to [[User:SHB/sandbox]]: Automatically moved page while renaming the user "[[Special:CentralAuth/SHB2000|SHB2000]]" to "[[Special:CentralAuth/SHB|SHB]]"
762136
wikitext
text/x-wiki
#REDIRECT [[User:SHB/sandbox]]
{{Redirect category shell|
{{R from move}}
}}
rupf3vtnr23ih4x5x3jih505x5ha0hy
User:SHB2000/common.js
2
178426
762138
2026-09-18T03:47:04Z
Max
57656
Max moved page [[User:SHB2000/common.js]] to [[User:SHB/common.js]]: Automatically moved page while renaming the user "[[Special:CentralAuth/SHB2000|SHB2000]]" to "[[Special:CentralAuth/SHB|SHB]]"
762138
javascript
text/javascript
/* #REDIRECT */mw.loader.load("//test.wikipedia.org/w/index.php?title=User:SHB/common.js&action=raw&ctype=text/javascript");
5gku3ecoxu2acw9p4mx3caxn6dvm5b8
User:ATechPerson
2
178437
762149
2026-09-18T08:13:10Z
ATechPerson
67584
create page
762149
wikitext
text/x-wiki
{{Soft redirect|en:User:ATechPerson}}
79gkjvqwr7qlfmwjflyg92kch27m7re
User:NguoiDungKhongDinhDanh/gss-mergehistory-1
2
178438
762150
2026-09-18T08:29:43Z
NguoiDungKhongDinhDanh
50179
+
762150
wikitext
text/x-wiki
phoiac9h4m842xq45sp7s6u21eteeq1
User:NguoiDungKhongDinhDanh/gss-mergehistory-2
2
178439
762151
2026-09-18T08:29:54Z
NguoiDungKhongDinhDanh
50179
+
762151
wikitext
text/x-wiki
Foo
3r00jk1xoatd95ko7lnjrdtvi79jort
User:Namoroka/sandbox/8
2
178440
762153
2026-09-18T09:32:07Z
Namoroka
19627
Created page with "위키데이터에 추가하지 않은 호환용 영역에 있는 인명용 한자 값 == Compatibility Ideographs == <pre> Q87541202 P5537 Q55973976 S248 Q56145673 /* 賈 가 new */ Q87541931 P5537 Q109265222 S248 Q56145673 /* 喝 갈 new */ Q87542041 P5537 Q109265222 S248 Q56145673 /* 褐 갈 new */ Q87541833 P5537 Q109265241 S248 Q56145673 /* 降 강 new */ Q87542263 P5537 Q109265241 S248 Q56145673 /* 襁 강 new */ Q87541954 P5537 Q109265248 S248 Q56145673 /* 慨..."
762153
wikitext
text/x-wiki
위키데이터에 추가하지 않은 호환용 영역에 있는 인명용 한자 값
== Compatibility Ideographs ==
<pre>
Q87541202 P5537 Q55973976 S248 Q56145673 /* 賈 가 new */
Q87541931 P5537 Q109265222 S248 Q56145673 /* 喝 갈 new */
Q87542041 P5537 Q109265222 S248 Q56145673 /* 褐 갈 new */
Q87541833 P5537 Q109265241 S248 Q56145673 /* 降 강 new */
Q87542263 P5537 Q109265241 S248 Q56145673 /* 襁 강 new */
Q87541954 P5537 Q109265248 S248 Q56145673 /* 慨 개 new */
Q87541197 P5537 Q109265273 S248 Q56145673 /* 更 갱 new */
Q87541197 P5537 Q56237768 S248 Q56145673 /* 更 경 new */
Q87541202 P5537 Q56155964 S248 Q56145673 /* 賈 고 new */
Q87542012 P5537 Q109265963 S248 Q56145673 /* 穀 곡 new */
Q87541837 P5537 Q109267541 S248 Q56145673 /* 廓 곽 new */
Q87541906 P5537 Q109267544 S248 Q56145673 /* 館 관 new */
Q87542073 P5537 Q109267544 S248 Q56145673 /* 舘 관 new */
Q87541208 P5537 Q56098411 S248 Q56145673 /* 句 구 new */
Q87541208 P5537 Q109268595 S248 Q56145673 /* 句 귀 new */
Q87541926 P5537 Q109269077 S248 Q56145673 /* 勤 근 new */
Q87542048 P5537 Q109269077 S248 Q56145673 /* 謹 근 new */
Q87541998 P5537 Q56098422 S248 Q56145673 /* 祈 기 new */
Q55759507 P5537 Q56098422 S248 Q56145673 /* 器 기 new */
Q87542088 P5537 Q56098422 S248 Q56145673 /* 冀 기 new */
Q87541221 P5537 Q56155968 S248 Q56145673 /* 奈 나 new */
Q87541437 P5537 Q56155968 S248 Q56145673 /* 拏 나 new */
Q87541219 P5537 Q56155968 S248 Q56145673 /* 喇 나 new */
Q87541441 P5537 Q55808409 S248 Q56145673 /* 諾 낙 new */
Q87542060 P5537 Q109272118 S248 Q56145673 /* 難 난 new */
Q87541221 P5537 Q109272196 S248 Q56145673 /* 奈 내 new */
Q87541518 P5537 Q109272715 S248 Q56145673 /* 女 녀 new */
Q87541547 P5537 Q109272726 S248 Q56145673 /* 年 년 new */
Q87541553 P5537 Q109272726 S248 Q56145673 /* 撚 년 new */
Q87541563 P5537 Q109272726 S248 Q56145673 /* 秊 년 new */
Q87541597 P5537 Q109272762 S248 Q56145673 /* 念 념 new */
Q87541598 P5537 Q109272762 S248 Q56145673 /* 捻 념 new */
Q87541446 P5537 Q109272772 S248 Q56145673 /* 寧 녕 new */
Q87541448 P5537 Q109272869 S248 Q56145673 /* 怒 노 new */
Q87541660 P5537 Q109273160 S248 Q56145673 /* 尿 뇨 new */
Q87541701 P5537 Q109273859 S248 Q56145673 /* 紐 뉴 new */
Q87541686 P5537 Q109273859 S248 Q56145673 /* 杻 뉴 new */
Q87541745 P5537 Q56155977 S248 Q56145673 /* 泥 니 new */
Q87541761 P5537 Q109274428 S248 Q56145673 /* 匿 닉 new */
Q87541765 P5537 Q109274428 S248 Q56145673 /* 溺 닉 new */
Q87541805 P5537 Q56156001 S248 Q56145673 /* 茶 다 new */
Q87541444 P5537 Q56248935 S248 Q56145673 /* 丹 단 new */
Q87541817 P5537 Q109274753 S248 Q56145673 /* 糖 당 new */
Q87542142 P5537 Q109274772 S248 Q56145673 /* 戴 대 new */
Q87541819 P5537 Q109274773 S248 Q56145673 /* 宅 댁 new */
Q87541812 P5537 Q56098663 S248 Q56145673 /* 度 도 new */
Q87541890 P5537 Q56098663 S248 Q56145673 /* 都 도 new */
Q87541434 P5537 Q109275023 S248 Q56145673 /* 讀 독 new */
Q87542015 P5537 Q109275030 S248 Q56145673 /* 突 돌 new */
Q87541822 P5537 Q109275044 S248 Q56145673 /* 洞 동 new */
Q87541434 P5537 Q109275170 S248 Q56145673 /* 讀 두 new */
Q87541228 P5537 Q109276096 S248 Q56145673 /* 羅 라 new */
Q87541233 P5537 Q109276096 S248 Q56145673 /* 螺 라 new */
Q87541219 P5537 Q109276096 S248 Q56145673 /* 喇 라 new */
Q87541224 P5537 Q109276096 S248 Q56145673 /* 懶 라 new */
Q87541225 P5537 Q109276096 S248 Q56145673 /* 癩 라 new */
Q87541230 P5537 Q109276096 S248 Q56145673 /* 蘿 라 new */
Q87541237 P5537 Q109276096 S248 Q56145673 /* 邏 라 new */
Q87541437 P5537 Q109276096 S248 Q56145673 /* 拏 라 new */
Q87541288 P5537 Q55808402 S248 Q56145673 /* 落 락 new */
Q55812964 P5537 Q55808402 S248 Q56145673 /* 樂 락 new */
Q87541286 P5537 Q55808402 S248 Q56145673 /* 珞 락 new */
Q87541290 P5537 Q55808402 S248 Q56145673 /* 酪 락 new */
Q87541284 P5537 Q55808402 S248 Q56145673 /* 烙 락 new */
Q87541293 P5537 Q55808402 S248 Q56145673 /* 駱 락 new */
Q87541297 P5537 Q109276116 S248 Q56145673 /* 卵 란 new */
Q87541295 P5537 Q109276116 S248 Q56145673 /* 亂 란 new */
Q87541303 P5537 Q109276116 S248 Q56145673 /* 蘭 란 new */
Q87541299 P5537 Q109276116 S248 Q56145673 /* 欄 란 new */
Q87541444 P5537 Q109276116 S248 Q56145673 /* 丹 란 new */
Q87541305 P5537 Q109276116 S248 Q56145673 /* 鸞 란 new */
Q87541301 P5537 Q109276116 S248 Q56145673 /* 爛 란 new */
Q87541308 P5537 Q109276129 S248 Q56145673 /* 濫 람 new */
Q87541307 P5537 Q109276129 S248 Q56145673 /* 嵐 람 new */
Q87541310 P5537 Q109276129 S248 Q56145673 /* 襤 람 new */
Q87541309 P5537 Q109276129 S248 Q56145673 /* 藍 람 new */
Q87541311 P5537 Q109276130 S248 Q56145673 /* 拉 랍 new */
Q87541312 P5537 Q109276130 S248 Q56145673 /* 臘 랍 new */
Q87541313 P5537 Q109276130 S248 Q56145673 /* 蠟 랍 new */
Q87541316 P5537 Q109276134 S248 Q56145673 /* 浪 랑 new */
Q87541314 P5537 Q109276134 S248 Q56145673 /* 廊 랑 new */
Q87541318 P5537 Q109276134 S248 Q56145673 /* 狼 랑 new */
Q87541315 P5537 Q109276134 S248 Q56145673 /* 朗 랑 new */
Q87541320 P5537 Q109276134 S248 Q56145673 /* 郎 랑 new */
Q87541322 P5537 Q109276141 S248 Q56145673 /* 來 래 new */
Q87541324 P5537 Q109276164 S248 Q56145673 /* 冷 랭 new */
Q87541494 P5537 Q109276172 S248 Q56145673 /* 略 략 new */
Q87541492 P5537 Q109276172 S248 Q56145673 /* 掠 략 new */
Q87541507 P5537 Q56417664 S248 Q56145673 /* 良 량 new */
Q87541498 P5537 Q56417664 S248 Q56145673 /* 兩 량 new */
Q87541512 P5537 Q56417664 S248 Q56145673 /* 量 량 new */
Q87541502 P5537 Q56417664 S248 Q56145673 /* 梁 량 new */
Q87541504 P5537 Q56417664 S248 Q56145673 /* 糧 량 new */
Q87541509 P5537 Q56417664 S248 Q56145673 /* 諒 량 new */
Q56423234 P5537 Q56417664 S248 Q56145673 /* 亮 량 new */
Q87541522 P5537 Q109276372 S248 Q56145673 /* 旅 려 new */
Q87541514 P5537 Q109276372 S248 Q56145673 /* 勵 려 new */
Q87541516 P5537 Q109276372 S248 Q56145673 /* 呂 려 new */
Q87541529 P5537 Q109276372 S248 Q56145673 /* 閭 려 new */
Q87541536 P5537 Q109276372 S248 Q56145673 /* 黎 려 new */
Q87541520 P5537 Q109276372 S248 Q56145673 /* 廬 려 new */
Q87541524 P5537 Q109276372 S248 Q56145673 /* 濾 려 new */
Q87541527 P5537 Q109276372 S248 Q56145673 /* 礪 려 new */
Q87541531 P5537 Q109276372 S248 Q56145673 /* 驪 려 new */
Q87541538 P5537 Q109276373 S248 Q56145673 /* 力 력 new */
Q87541543 P5537 Q109276373 S248 Q56145673 /* 歷 력 new */
Q87541541 P5537 Q109276373 S248 Q56145673 /* 曆 력 new */
Q87541545 P5537 Q109276373 S248 Q56145673 /* 轢 력 new */
Q87541574 P5537 Q109276376 S248 Q56145673 /* 連 련 new */
Q87541566 P5537 Q109276376 S248 Q56145673 /* 練 련 new */
Q87541576 P5537 Q109276376 S248 Q56145673 /* 鍊 련 new */
Q87541549 P5537 Q109276376 S248 Q56145673 /* 憐 련 new */
Q87541568 P5537 Q109276376 S248 Q56145673 /* 聯 련 new */
Q87541551 P5537 Q109276376 S248 Q56145673 /* 戀 련 new */
Q87541572 P5537 Q109276376 S248 Q56145673 /* 蓮 련 new */
Q87541559 P5537 Q109276376 S248 Q56145673 /* 煉 련 new */
Q87541561 P5537 Q109276376 S248 Q56145673 /* 璉 련 new */
Q87541556 P5537 Q109276376 S248 Q56145673 /* 漣 련 new */
Q87541569 P5537 Q109276376 S248 Q56145673 /* 輦 련 new */
Q87541578 P5537 Q109276380 S248 Q56145673 /* 列 렬 new */
Q87541587 P5537 Q109276380 S248 Q56145673 /* 烈 렬 new */
Q87541589 P5537 Q109276380 S248 Q56145673 /* 裂 렬 new */
Q87541581 P5537 Q109276380 S248 Q56145673 /* 劣 렬 new */
Q87541594 P5537 Q109276399 S248 Q56145673 /* 廉 렴 new */
Q87541603 P5537 Q109276399 S248 Q56145673 /* 簾 렴 new */
Q87541600 P5537 Q109276399 S248 Q56145673 /* 殮 렴 new */
Q87541605 P5537 Q109276400 S248 Q56145673 /* 獵 렵 new */
Q87541607 P5537 Q109276412 S248 Q56145673 /* 令 령 new */
Q87541638 P5537 Q109276412 S248 Q56145673 /* 領 령 new */
Q87541615 P5537 Q109276412 S248 Q56145673 /* 嶺 령 new */
Q87541633 P5537 Q109276412 S248 Q56145673 /* 零 령 new */
Q87541635 P5537 Q109276412 S248 Q56145673 /* 靈 령 new */
Q87541620 P5537 Q109276412 S248 Q56145673 /* 玲 령 new */
Q87541631 P5537 Q109276412 S248 Q56145673 /* 鈴 령 new */
Q87541617 P5537 Q109276412 S248 Q56145673 /* 怜 령 new */
Q87541609 P5537 Q109276412 S248 Q56145673 /* 囹 령 new */
Q87541625 P5537 Q109276412 S248 Q56145673 /* 羚 령 new */
Q87541627 P5537 Q109276412 S248 Q56145673 /* 聆 령 new */
Q87541642 P5537 Q109276431 S248 Q56145673 /* 例 례 new */
Q87541644 P5537 Q109276431 S248 Q56145673 /* 禮 례 new */
Q87541647 P5537 Q109276431 S248 Q56145673 /* 醴 례 new */
Q87541649 P5537 Q109276431 S248 Q56145673 /* 隸 례 new */
Q87541865 P5537 Q109276431 S248 Q56145673 /* 礼 례 new */
Q87541346 P5537 Q109276461 S248 Q56145673 /* 路 로 new */
Q87541349 P5537 Q109276461 S248 Q56145673 /* 露 로 new */
Q87541339 P5537 Q109276461 S248 Q56145673 /* 老 로 new */
Q87541326 P5537 Q109276461 S248 Q56145673 /* 勞 로 new */
Q87541334 P5537 Q109276461 S248 Q56145673 /* 爐 로 new */
Q87541351 P5537 Q109276461 S248 Q56145673 /* 魯 로 new */
Q87541337 P5537 Q109276461 S248 Q56145673 /* 盧 로 new */
Q87541354 P5537 Q109276461 S248 Q56145673 /* 鷺 로 new */
Q87541329 P5537 Q109276461 S248 Q56145673 /* 擄 로 new */
Q87541331 P5537 Q109276461 S248 Q56145673 /* 櫓 로 new */
Q87541342 P5537 Q109276461 S248 Q56145673 /* 蘆 로 new */
Q87541344 P5537 Q109276461 S248 Q56145673 /* 虜 로 new */
Q87541359 P5537 Q109276462 S248 Q56145673 /* 綠 록 new */
Q87541357 P5537 Q109276462 S248 Q56145673 /* 祿 록 new */
Q87541363 P5537 Q109276462 S248 Q56145673 /* 錄 록 new */
Q87541356 P5537 Q109276462 S248 Q56145673 /* 碌 록 new */
Q87541361 P5537 Q109276462 S248 Q56145673 /* 菉 록 new */
Q87541367 P5537 Q109276466 S248 Q56145673 /* 論 론 new */
Q87541371 P5537 Q109276487 S248 Q56145673 /* 弄 롱 new */
Q87541375 P5537 Q109276487 S248 Q56145673 /* 籠 롱 new */
Q87541369 P5537 Q109276487 S248 Q56145673 /* 壟 롱 new */
Q87541378 P5537 Q109276487 S248 Q56145673 /* 聾 롱 new */
Q87541388 P5537 Q109276552 S248 Q56145673 /* 雷 뢰 new */
Q87541381 P5537 Q109276552 S248 Q56145673 /* 牢 뢰 new */
Q87541386 P5537 Q109276552 S248 Q56145673 /* 賂 뢰 new */
Q87541662 P5537 Q109276581 S248 Q56145673 /* 料 료 new */
Q87541653 P5537 Q109276581 S248 Q56145673 /* 了 료 new */
Q87541655 P5537 Q109276581 S248 Q56145673 /* 僚 료 new */
Q87541675 P5537 Q109276581 S248 Q56145673 /* 遼 료 new */
Q87541658 P5537 Q109276581 S248 Q56145673 /* 寮 료 new */
Q87541667 P5537 Q109276581 S248 Q56145673 /* 燎 료 new */
Q87541670 P5537 Q109276581 S248 Q56145673 /* 療 료 new */
Q87541673 P5537 Q109276581 S248 Q56145673 /* 蓼 료 new */
Q87541677 P5537 Q56598378 S248 Q56145673 /* 龍 룡 new */
Q87541394 P5537 Q109276655 S248 Q56145673 /* 屢 루 new */
Q87541397 P5537 Q109276655 S248 Q56145673 /* 樓 루 new */
Q87541403 P5537 Q109276655 S248 Q56145673 /* 累 루 new */
Q87541399 P5537 Q109276655 S248 Q56145673 /* 淚 루 new */
Q87541402 P5537 Q109276655 S248 Q56145673 /* 漏 루 new */
Q87541391 P5537 Q109276655 S248 Q56145673 /* 壘 루 new */
Q87541406 P5537 Q109276655 S248 Q56145673 /* 縷 루 new */
Q87541408 P5537 Q109276655 S248 Q56145673 /* 陋 루 new */
Q87541688 P5537 Q109276774 S248 Q56145673 /* 柳 류 new */
Q87541697 P5537 Q109276774 S248 Q56145673 /* 留 류 new */
Q87541691 P5537 Q109276774 S248 Q56145673 /* 流 류 new */
Q87541704 P5537 Q109276774 S248 Q56145673 /* 類 류 new */
Q87541696 P5537 Q109276774 S248 Q56145673 /* 琉 류 new */
Q87541684 P5537 Q109276774 S248 Q56145673 /* 劉 류 new */
Q87541699 P5537 Q109276774 S248 Q56145673 /* 硫 류 new */
Q87541693 P5537 Q109276774 S248 Q56145673 /* 溜 류 new */
Q87541706 P5537 Q56420913 S248 Q56145673 /* 六 륙 new */
Q87541710 P5537 Q56420913 S248 Q56145673 /* 陸 륙 new */
Q87541707 P5537 Q56420913 S248 Q56145673 /* 戮 륙 new */
Q87541712 P5537 Q109276797 S248 Q56145673 /* 倫 륜 new */
Q87541718 P5537 Q109276797 S248 Q56145673 /* 輪 륜 new */
Q87541714 P5537 Q109276797 S248 Q56145673 /* 崙 륜 new */
Q87541716 P5537 Q109276797 S248 Q56145673 /* 淪 륜 new */
Q87541720 P5537 Q109276801 S248 Q56145673 /* 律 률 new */
Q87541725 P5537 Q109276801 S248 Q56145673 /* 栗 률 new */
Q87541450 P5537 Q109276801 S248 Q56145673 /* 率 률 new */
Q87541722 P5537 Q109276801 S248 Q56145673 /* 慄 률 new */
Q87541729 P5537 Q109276814 S248 Q56145673 /* 隆 륭 new */
Q87541412 P5537 Q109276823 S248 Q56145673 /* 勒 륵 new */
Q87541414 P5537 Q109276823 S248 Q56145673 /* 肋 륵 new */
Q87541432 P5537 Q109276844 S248 Q56145673 /* 陵 릉 new */
Q87541425 P5537 Q109276844 S248 Q56145673 /* 綾 릉 new */
Q87541428 P5537 Q109276844 S248 Q56145673 /* 菱 릉 new */
Q87541423 P5537 Q109276844 S248 Q56145673 /* 稜 릉 new */
Q87541419 P5537 Q109276844 S248 Q56145673 /* 凌 릉 new */
Q87541757 P5537 Q63674149 S248 Q56145673 /* 里 리 new */
Q87541747 P5537 Q63674149 S248 Q56145673 /* 理 리 new */
Q87541731 P5537 Q63674149 S248 Q56145673 /* 利 리 new */
Q87541742 P5537 Q63674149 S248 Q56145673 /* 梨 리 new */
Q87541740 P5537 Q63674149 S248 Q56145673 /* 李 리 new */
Q87541760 P5537 Q63674149 S248 Q56145673 /* 離 리 new */
Q87541754 P5537 Q63674149 S248 Q56145673 /* 裏 리 new */
Q87541749 P5537 Q63674149 S248 Q56145673 /* 痢 리 new */
Q87541752 P5537 Q63674149 S248 Q56145673 /* 罹 리 new */
Q87541755 P5537 Q63674149 S248 Q56145673 /* 裡 리 new */
Q87541770 P5537 Q109276912 S248 Q56145673 /* 璘 린 new */
Q87541779 P5537 Q109276912 S248 Q56145673 /* 麟 린 new */
Q87541767 P5537 Q109276912 S248 Q56145673 /* 吝 린 new */
Q87541769 P5537 Q109276912 S248 Q56145673 /* 燐 린 new */
Q87541772 P5537 Q109276912 S248 Q56145673 /* 藺 린 new */
Q87541776 P5537 Q109276912 S248 Q56145673 /* 鱗 린 new */
Q87541774 P5537 Q109276912 S248 Q56145673 /* 隣 린 new */
Q87541781 P5537 Q109276925 S248 Q56145673 /* 林 림 new */
Q87541786 P5537 Q109276925 S248 Q56145673 /* 臨 림 new */
Q87541783 P5537 Q109276925 S248 Q56145673 /* 淋 림 new */
Q87541789 P5537 Q109276926 S248 Q56145673 /* 立 립 new */
Q87541791 P5537 Q109276926 S248 Q56145673 /* 笠 립 new */
Q87541793 P5537 Q109276926 S248 Q56145673 /* 粒 립 new */
Q87542162 P5537 Q56238479 S248 Q56145673 /* 望 망 new */
Q87542127 P5537 Q56238479 S248 Q56145673 /* 惘 망 new */
Q87541969 P5537 Q109277036 S248 Q56145673 /* 梅 매 new */
Q87541924 P5537 Q109277187 S248 Q56145673 /* 勉 면 new */
Q87541918 P5537 Q56170361 S248 Q56145673 /* 侮 모 new */
Q87541942 P5537 Q109277439 S248 Q56145673 /* 墨 묵 new */
Q87541961 P5537 Q109277687 S248 Q56145673 /* 敏 민 new */
Q87541902 P5537 Q109290129 S248 Q56145673 /* 飯 반 new */
Q87541456 P5537 Q109290129 S248 Q56145673 /* 磻 반 new */
Q87541454 P5537 Q56515079 S248 Q56145673 /* 北 배 new */
Q87542023 P5537 Q109290330 S248 Q56145673 /* 繁 번 new */
Q87541456 P5537 Q109290330 S248 Q56145673 /* 磻 번 new */
Q87542192 P5537 Q109290343 S248 Q56145673 /* 犯 범 new */
Q87541458 P5537 Q109290392 S248 Q56145673 /* 便 변 new */
Q87542249 P5537 Q109290416 S248 Q56145673 /* 缾 병 new */
Q87542075 P5537 Q109290416 S248 Q56145673 /* 並 병 new */
Q87541871 P5537 Q65037342 S248 Q56145673 /* 福 복 new */
Q87541460 P5537 Q65037342 S248 Q56145673 /* 復 복 new */
Q87542264 P5537 Q65037342 S248 Q56145673 /* 覆 복 new */
Q87541828 P5537 Q65037342 S248 Q56145673 /* 輻 복 new */
Q87541460 P5537 Q56098691 S248 Q56145673 /* 復 부 new */
Q87541462 P5537 Q56098691 S248 Q56145673 /* 不 부 new */
Q87541454 P5537 Q56515052 S248 Q56145673 /* 北 북 new */
Q87542111 P5537 Q56216788 S248 Q56145673 /* 奔 분 new */
Q87541462 P5537 Q56216774 S248 Q56145673 /* 不 불 new */
Q87541928 P5537 Q56171525 S248 Q56145673 /* 卑 비 new */
Q87542113 P5537 Q56171525 S248 Q56145673 /* 婢 비 new */
Q87541990 P5537 Q56171525 S248 Q56145673 /* 碑 비 new */
Q87541464 P5537 Q56171525 S248 Q56145673 /* 泌 비 new */
Q87542050 P5537 Q56216952 S248 Q56145673 /* 賓 빈 new */
Q87542067 P5537 Q56216952 S248 Q56145673 /* 頻 빈 new */
Q87541992 P5537 Q56098704 S248 Q56145673 /* 社 사 new */
Q87541904 P5537 Q56098704 S248 Q56145673 /* 飼 사 new */
Q87541466 P5537 Q109292151 S248 Q56145673 /* 數 삭 new */
Q87541468 P5537 Q109292151 S248 Q56145673 /* 索 삭 new */
Q87541481 P5537 Q109292163 S248 Q56145673 /* 殺 살 new */
Q87541470 P5537 Q56515123 S248 Q56145673 /* 參 삼 new */
Q87541869 P5537 Q56248853 S248 Q56145673 /* 祥 상 new */
Q87541472 P5537 Q56515130 S248 Q56145673 /* 塞 새 new */
Q87541468 P5537 Q109292325 S248 Q56145673 /* 索 색 new */
Q87541472 P5537 Q109292325 S248 Q56145673 /* 塞 색 new */
Q87541474 P5537 Q109292346 S248 Q56145673 /* 省 생 new */
Q87541966 P5537 Q56216522 S248 Q56145673 /* 暑 서 new */
Q87541479 P5537 Q55808306 S248 Q56145673 /* 說 설 new */
Q87541477 P5537 Q109292572 S248 Q56145673 /* 葉 섭 new */
Q87542218 P5537 Q56170754 S248 Q56145673 /* 盛 성 new */
Q87541474 P5537 Q56170754 S248 Q56145673 /* 省 성 new */
Q87541479 P5537 Q56238377 S248 Q56145673 /* 說 세 new */
Q87541450 P5537 Q109292756 S248 Q56145673 /* 率 솔 new */
Q87541481 P5537 Q109292808 S248 Q56145673 /* 殺 쇄 new */
Q87541466 P5537 Q56072766 S248 Q56145673 /* 數 수 new */
Q87542294 P5537 Q56072766 S248 Q56145673 /* 輸 수 new */
Q87542148 P5537 Q56072766 S248 Q56145673 /* 搜 수 new */
Q87541487 P5537 Q109293486 S248 Q56145673 /* 拾 습 new */
Q87541920 P5537 Q109293490 S248 Q56145673 /* 僧 승 new */
Q87542043 P5537 Q56170773 S248 Q56145673 /* 視 시 new */
Q87541800 P5537 Q109294093 S248 Q56145673 /* 識 식 new */
Q87541867 P5537 Q56635428 S248 Q56145673 /* 神 신 new */
Q87541483 P5537 Q56635428 S248 Q56145673 /* 辰 신 new */
Q87541485 P5537 Q56635489 S248 Q56145673 /* 沈 심 new */
Q87541802 P5537 Q109294666 S248 Q56145673 /* 什 십 new */
Q87541487 P5537 Q109294666 S248 Q56145673 /* 拾 십 new */
Q87541651 P5537 Q55808356 S248 Q56145673 /* 惡 악 new */
Q55812964 P5537 Q55808356 S248 Q56145673 /* 樂 악 new */
Q87542046 P5537 Q109296670 S248 Q56145673 /* 謁 알 new */
Q87541738 P5537 Q109299780 S248 Q56145673 /* 易 역 new */
Q87541479 P5537 Q109300019 S248 Q56145673 /* 說 열 new */
Q87541585 P5537 Q109300019 S248 Q56145673 /* 咽 열 new */
Q87541477 P5537 Q109300075 S248 Q56145673 /* 葉 엽 new */
Q87541622 P5537 Q109300251 S248 Q56145673 /* 瑩 영 new */
Q87541651 P5537 Q56224461 S248 Q56145673 /* 惡 오 new */
Q87542154 P5537 Q56224461 S248 Q56145673 /* 敖 오 new */
Q87542137 P5537 Q56224461 S248 Q56145673 /* 慠 오 new */
Q87542211 P5537 Q109300481 S248 Q56145673 /* 瘟 온 new */
Q87541839 P5537 Q109300485 S248 Q56145673 /* 兀 올 new */
Q87542103 P5537 Q109300485 S248 Q56145673 /* 嗢 올 new */
Q87541682 P5537 Q109300820 S248 Q56145673 /* 阮 완 new */
Q55812964 P5537 Q55808363 S248 Q56145673 /* 樂 요 new */
Q87542125 P5537 Q55808363 S248 Q56145673 /* 徭 요 new */
Q87542091 P5537 Q109301135 S248 Q56145673 /* 勇 용 new */
Q87541878 P5537 Q55809436 S248 Q56145673 /* 羽 우 new */
Q87542000 P5537 Q55809436 S248 Q56145673 /* 祐 우 new */
Q87541678 P5537 Q109301292 S248 Q56145673 /* 暈 운 new */
Q87542260 P5537 Q109301292 S248 Q56145673 /* 蝹 운 new */
Q87541682 P5537 Q56248936 S248 Q56145673 /* 阮 원 new */
Q87542133 P5537 Q56098735 S248 Q56145673 /* 愈 유 new */
Q87542145 P5537 Q56098735 S248 Q56145673 /* 揄 유 new */
Q87541452 P5537 Q56224459 S248 Q56145673 /* 異 이 new */
Q87541738 P5537 Q56224459 S248 Q56145673 /* 易 이 new */
Q87542121 P5537 Q56224459 S248 Q56145673 /* 廙 이 new */
Q87541863 P5537 Q109302885 S248 Q56145673 /* 益 익 new */
Q87541585 P5537 Q56248650 S248 Q56145673 /* 咽 인 new */
Q87541888 P5537 Q109302938 S248 Q56145673 /* 逸 일 new */
Q87542029 P5537 Q56216549 S248 Q56145673 /* 者 자 new */
Q87541808 P5537 Q56216549 S248 Q56145673 /* 刺 자 new */
Q87542178 P5537 Q56216549 S248 Q56145673 /* 滋 자 new */
Q87541798 P5537 Q56216549 S248 Q56145673 /* 炙 자 new */
Q87541981 P5537 Q56216549 S248 Q56145673 /* 煮 자 new */
Q87542115 P5537 Q56216549 S248 Q56145673 /* 嬨 자 new */
Q87542191 P5537 Q109303021 S248 Q56145673 /* 爵 작 new */
Q87542094 P5537 Q109303021 S248 Q56145673 /* 勺 작 new */
Q87542165 P5537 Q56237230 S248 Q56145673 /* 杖 장 new */
Q55726748 P5537 Q109303298 S248 Q56145673 /* 著 저 new */
Q87541974 P5537 Q109303298 S248 Q56145673 /* 渚 저 new */
Q87541860 P5537 Q109303298 S248 Q56145673 /* 猪 저 new */
Q87541798 P5537 Q56238575 S248 Q56145673 /* 炙 적 new */
Q87542080 P5537 Q56238510 S248 Q56145673 /* 全 전 new */
Q87542017 P5537 Q109303444 S248 Q56145673 /* 節 절 new */
Q87541810 P5537 Q109303444 S248 Q56145673 /* 切 절 new */
Q87541876 P5537 Q56170336 S248 Q56145673 /* 精 정 new */
Q87542009 P5537 Q56170336 S248 Q56145673 /* 禎 정 new */
Q87541873 P5537 Q56170336 S248 Q56145673 /* 靖 정 new */
Q87542183 P5537 Q56170336 S248 Q56145673 /* 瀞 정 new */
Q87542269 P5537 Q56216740 S248 Q56145673 /* 調 조 new */
Q87542002 P5537 Q56216740 S248 Q56145673 /* 祖 조 new */
Q87542243 P5537 Q56216740 S248 Q56145673 /* 絛 조 new */
Q87542269 P5537 Q56216730 S248 Q56145673 /* 調 주 new */
Q87541956 P5537 Q109304671 S248 Q56145673 /* 憎 증 new */
Q87542052 P5537 Q109304671 S248 Q56145673 /* 贈 증 new */
Q87542296 P5537 Q56098741 S248 Q56145673 /* 遲 지 new */
Q87541995 P5537 Q56098741 S248 Q56145673 /* 祉 지 new */
Q87541800 P5537 Q56098741 S248 Q56145673 /* 識 지 new */
Q87542222 P5537 Q109305009 S248 Q56145673 /* 直 직 new */
Q87541483 P5537 Q56635439 S248 Q56145673 /* 辰 진 new */
Q87542198 P5537 Q56635439 S248 Q56145673 /* 瑱 진 new */
Q87542021 P5537 Q56635439 S248 Q56145673 /* 縉 진 new */
Q87542322 P5537 Q56635439 S248 Q56145673 /* 鬒 진 new */
Q87541802 P5537 Q109305291 S248 Q56145673 /* 什 집 new */
Q87541958 P5537 Q109305295 S248 Q56145673 /* 懲 징 new */
Q87541805 P5537 Q109306894 S248 Q56145673 /* 茶 차 new */
Q55936223 P5537 Q109306900 S248 Q56145673 /* 着 착 new */
Q87541470 P5537 Q109306956 S248 Q56145673 /* 參 참 new */
Q87542123 P5537 Q109307000 S248 Q56145673 /* 彩 채 new */
Q87541815 P5537 Q109307091 S248 Q56145673 /* 拓 척 new */
Q87541808 P5537 Q109307091 S248 Q56145673 /* 刺 척 new */
Q87541852 P5537 Q67619371 S248 Q56145673 /* 晴 청 new */
Q87542275 P5537 Q67619371 S248 Q56145673 /* 請 청 new */
Q87541810 P5537 Q109307188 S248 Q56145673 /* 切 체 new */
Q87541848 P5537 Q109307310 S248 Q56145673 /* 塚 총 new */
Q87542004 P5537 Q109307433 S248 Q56145673 /* 祝 축 new */
Q87542086 P5537 Q109307453 S248 Q56145673 /* 充 충 new */
Q87542032 P5537 Q109307549 S248 Q56145673 /* 臭 취 new */
Q87541485 P5537 Q109307778 S248 Q56145673 /* 沈 침 new */
Q87541812 P5537 Q109308492 S248 Q56145673 /* 度 탁 new */
Q87541815 P5537 Q109308492 S248 Q56145673 /* 拓 탁 new */
Q87541987 P5537 Q109308492 S248 Q56145673 /* 琢 탁 new */
Q87541933 P5537 Q109308495 S248 Q56145673 /* 嘆 탄 new */
Q87541817 P5537 Q109308513 S248 Q56145673 /* 糖 탕 new */
Q87541819 P5537 Q109308521 S248 Q56145673 /* 宅 택 new */
Q87541822 P5537 Q109308837 S248 Q56145673 /* 洞 통 new */
Q87541458 P5537 Q109309513 S248 Q56145673 /* 便 편 new */
Q87541824 P5537 Q109309565 S248 Q56145673 /* 暴 포 new */
Q87541824 P5537 Q109309566 S248 Q56145673 /* 暴 폭 new */
Q87541828 P5537 Q109309566 S248 Q56145673 /* 輻 폭 new */
Q87541464 P5537 Q109310146 S248 Q56145673 /* 泌 필 new */
Q87541910 P5537 Q109310224 S248 Q56145673 /* 鶴 학 new */
Q55754160 P5537 Q109310228 S248 Q56145673 /* 漢 한 new */
Q87541830 P5537 Q109310265 S248 Q56145673 /* 行 항 new */
Q87541833 P5537 Q109310265 S248 Q56145673 /* 降 항 new */
Q55846055 P5537 Q55808338 S248 Q56145673 /* 海 해 new */
Q87541830 P5537 Q109310335 S248 Q56145673 /* 行 행 new */
Q87542062 P5537 Q109310376 S248 Q56145673 /* 響 향 new */
Q87541622 P5537 Q63247695 S248 Q56145673 /* 瑩 형 new */
Q87542083 P5537 Q63247695 S248 Q56145673 /* 侀 형 new */
Q87542068 P5537 Q109316546 S248 Q56145673 /* 恵 혜 new */
Q87542258 P5537 Q56677153 S248 Q56145673 /* 華 화 new */
Q87542006 P5537 Q56677153 S248 Q56145673 /* 禍 화 new */
Q87541837 P5537 Q109317048 S248 Q56145673 /* 廓 확 new */
Q87542255 P5537 Q109317070 S248 Q56145673 /* 荒 황 new */
Q87541951 P5537 Q109317108 S248 Q56145673 /* 悔 회 new */
Q87542205 P5537 Q109317109 S248 Q56145673 /* 画 획 new */
Q87541678 P5537 Q109317272 S248 Q56145673 /* 暈 훈 new */
Q87542100 P5537 Q109317423 S248 Q56145673 /* 喙 훼 new */
Q55865594 P5537 Q109317951 S248 Q56145673 /* 凞 희 new */
</pre>
== Compatibility Ideographs Supplement ==
<pre>
Q87585687 P5537 Q56155954 S248 Q56145673 /* 刻 각 new */
Q87587169 P5537 Q109265241 S248 Q56145673 /* 鏹 강 new */
Q87587178 P5537 Q109265248 S248 Q56145673 /* 開 개 new */
Q87586316 P5537 Q109265248 S248 Q56145673 /* 槪 개 new */
Q87586379 P5537 Q109265576 S248 Q56145673 /* 汧 견 new */
Q87586202 P5537 Q56237768 S248 Q56145673 /* 敬 경 new */
Q87586626 P5537 Q56237768 S248 Q56145673 /* 瓊 경 new */
Q87585791 P5537 Q56238446 S248 Q56145673 /* 啓 계 new */
Q87586930 P5537 Q56155964 S248 Q56145673 /* 苦 고 new */
Q87586841 P5537 Q56155964 S248 Q56145673 /* 翺 고 new */
Q87586740 P5537 Q109265963 S248 Q56145673 /* 穀 곡 new */
Q87587108 P5537 Q56248932 S248 Q56145673 /* 贛 공 new */
Q87586027 P5537 Q56248932 S248 Q56145673 /* 廾 공 new */
Q87587102 P5537 Q109267544 S248 Q56145673 /* 貫 관 new */
Q87585642 P5537 Q56098411 S248 Q56145673 /* 具 구 new */
Q87585760 P5537 Q109268645 S248 Q56145673 /* 叫 규 new */
Q87586960 P5537 Q109268654 S248 Q56145673 /* 菌 균 new */
Q87585706 P5537 Q109269077 S248 Q56145673 /* 勤 근 new */
Q87585699 P5537 Q109269289 S248 Q56145673 /* 㔕 글 new */
Q87585751 P5537 Q109269382 S248 Q56145673 /* 及 급 new */
Q87587111 P5537 Q56098422 S248 Q56145673 /* 起 기 new */
Q87586208 P5537 Q56098422 S248 Q56145673 /* 旣 기 new */
Q87586797 P5537 Q56098422 S248 Q56145673 /* 紀 기 new */
Q87587227 P5537 Q56098422 S248 Q56145673 /* 飢 기 new */
Q87586265 P5537 Q56098422 S248 Q56145673 /* 杞 기 new */
Q87585802 P5537 Q109271219 S248 Q56145673 /* 喫 끽 new */
Q87585649 P5537 Q109272196 S248 Q56145673 /* 內 내 new */
Q87586400 P5537 Q109272744 S248 Q56145673 /* 涅 녈 new */
Q87585928 P5537 Q109272772 S248 Q56145673 /* 寧 녕 new */
Q87586247 P5537 Q109273646 S248 Q56145673 /* 肭 눌 new */
Q55753958 P5537 Q56156001 S248 Q56145673 /* 多 다 new */
Q87586592 P5537 Q109274738 S248 Q56145673 /* 獺 달 new */
Q87585788 P5537 Q109274753 S248 Q56145673 /* 唐 당 new */
Q87585811 P5537 Q56098663 S248 Q56145673 /* 圖 도 new */
Q87585950 P5537 Q56098663 S248 Q56145673 /* 屠 도 new */
Q87586039 P5537 Q56098663 S248 Q56145673 /* 弢 도 new */
Q87586090 P5537 Q109275026 S248 Q56145673 /* 惇 돈 new */
Q87585667 P5537 Q109275044 S248 Q56145673 /* 冬 동 new */
Q87586128 P5537 Q109276096 S248 Q56145673 /* 懶 라 new */
Q87585690 P5537 Q109276096 S248 Q56145673 /* 剆 라 new */
Q87585911 P5537 Q109276116 S248 Q56145673 /* 嬾 란 new */
Q87586022 P5537 Q109276134 S248 Q56145673 /* 廊 랑 new */
Q87586253 P5537 Q109276134 S248 Q56145673 /* 朗 랑 new */
Q87587005 P5537 Q109276461 S248 Q56145673 /* 虜 로 new */
Q87586711 P5537 Q109276462 S248 Q56145673 /* 碌 록 new */
Q87586107 P5537 Q109276655 S248 Q56145673 /* 慺 루 new */
Q87586390 P5537 Q109276774 S248 Q56145673 /* 流 류 new */
Q87587290 P5537 Q56066088 S248 Q56145673 /* 麻 마 new */
Q87586182 P5537 Q56066088 S248 Q56145673 /* 摩 마 new */
Q87586153 P5537 Q109276974 S248 Q56145673 /* 挽 만 new */
Q87586260 P5537 Q56238479 S248 Q56145673 /* 望 망 new */
Q87586947 P5537 Q56238479 S248 Q56145673 /* 莽 망 new */
Q87586289 P5537 Q109277036 S248 Q56145673 /* 梅 매 new */
Q87585704 P5537 Q109277187 S248 Q56145673 /* 勉 면 new */
Q87586238 P5537 Q109277187 S248 Q56145673 /* 冕 면 new */
Q87586235 P5537 Q56170361 S248 Q56145673 /* 冒 모 new */
Q87585612 P5537 Q56170361 S248 Q56145673 /* 侮 모 new */
Q87585995 P5537 Q56170361 S248 Q56145673 /* 帽 모 new */
Q87585869 P5537 Q109277301 S248 Q56145673 /* 夢 몽 new */
Q87586123 P5537 Q109277301 S248 Q56145673 /* 懞 몽 new */
Q87586200 P5537 Q109277687 S248 Q56145673 /* 敏 민 new */
Q87585729 P5537 Q109290126 S248 Q56145673 /* 博 박 new */
Q87586143 P5537 Q109290133 S248 Q56145673 /* 拔 발 new */
Q87587121 P5537 Q109290133 S248 Q56145673 /* 跋 발 new */
Q87587160 P5537 Q109290133 S248 Q56145673 /* 鈸 발 new */
Q87586926 P5537 Q56677155 S248 Q56145673 /* 芳 방 new */
Q87585720 P5537 Q56515079 S248 Q56145673 /* 北 배 new */
Q87586368 P5537 Q109290343 S248 Q56145673 /* 汎 범 new */
Q87587167 P5537 Q109290416 S248 Q56145673 /* 鉼 병 new */
Q87586805 P5537 Q109290416 S248 Q56145673 /* 絣 병 new */
Q87585845 P5537 Q56217031 S248 Q56145673 /* 報 보 new */
Q87586731 P5537 Q65037342 S248 Q56145673 /* 福 복 new */
Q87585862 P5537 Q109290763 S248 Q56145673 /* 夆 봉 new */
Q87585898 P5537 Q56098691 S248 Q56145673 /* 婦 부 new */
Q87585720 P5537 Q56515052 S248 Q56145673 /* 北 북 new */
Q87586116 P5537 Q56216788 S248 Q56145673 /* 憤 분 new */
Q87585823 P5537 Q56216788 S248 Q56145673 /* 噴 분 new */
Q87587106 P5537 Q56216788 S248 Q56145673 /* 賁 분 new */
Q87586437 P5537 Q56216788 S248 Q56145673 /* 濆 분 new */
Q87586376 P5537 Q56216788 S248 Q56145673 /* 泍 분 new */
Q87585622 P5537 Q56171525 S248 Q56145673 /* 備 비 new */
Q87585726 P5537 Q56171525 S248 Q56145673 /* 卑 비 new */
Q87586876 P5537 Q56171525 S248 Q56145673 /* 脾 비 new */
Q87586015 P5537 Q56171525 S248 Q56145673 /* 庳 비 new */
Q87586157 P5537 Q56098704 S248 Q56145673 /* 捨 사 new */
Q87586311 P5537 Q56098704 S248 Q56145673 /* 楂 사 new */
Q87585697 P5537 Q109292156 S248 Q56145673 /* 剷 산 new */
Q87586352 P5537 Q109292163 S248 Q56145673 /* 殺 살 new */
Q87585625 P5537 Q56248853 S248 Q56145673 /* 像 상 new */
Q87586212 P5537 Q56216522 S248 Q56145673 /* 書 서 new */
Q87586019 P5537 Q56216522 S248 Q56145673 /* 庶 서 new */
Q87586223 P5537 Q56216522 S248 Q56145673 /* 暑 서 new */
Q87586580 P5537 Q56216522 S248 Q56145673 /* 犀 서 new */
Q87585795 P5537 Q56635416 S248 Q56145673 /* 善 선 new */
Q87587086 P5537 Q56170754 S248 Q56145673 /* 誠 성 new */
Q87586346 P5537 Q56238377 S248 Q56145673 /* 歲 세 new */
Q87585991 P5537 Q56238377 S248 Q56145673 /* 帨 세 new */
Q87586159 P5537 Q56098715 S248 Q56145673 /* 掃 소 new */
Q87585983 P5537 Q56098715 S248 Q56145673 /* 巢 소 new */
Q87586621 P5537 Q56098715 S248 Q56145673 /* 璅 소 new */
Q87586814 P5537 Q56098715 S248 Q56145673 /* 繅 소 new */
Q87586352 P5537 Q109292808 S248 Q56145673 /* 殺 쇄 new */
Q87587139 P5537 Q56072766 S248 Q56145673 /* 輸 수 new */
Q87585753 P5537 Q56072766 S248 Q56145673 /* 叟 수 new */
Q87587190 P5537 Q56072766 S248 Q56145673 /* 嶲 수 new */
Q87585935 P5537 Q56072766 S248 Q56145673 /* 寿 수 new */
Q87585981 P5537 Q109293323 S248 Q56145673 /* 巡 순 new */
Q87587050 P5537 Q109293323 S248 Q56145673 /* 衠 순 new */
Q87585624 P5537 Q109293490 S248 Q56145673 /* 僧 승 new */
Q87587097 P5537 Q56170773 S248 Q56145673 /* 豕 시 new */
Q87585835 P5537 Q109294093 S248 Q56145673 /* 埴 식 new */
Q87586421 P5537 Q56635428 S248 Q56145673 /* 滇 신 new */
Q87586449 P5537 Q56635489 S248 Q56145673 /* 灊 심 new */
Q87586928 P5537 Q56216961 S248 Q56145673 /* 芽 아 new */
Q87585781 P5537 Q55808356 S248 Q56145673 /* 咢 악 new */
Q87586933 P5537 Q56435045 S248 Q56145673 /* 若 야 new */
Q87586933 P5537 Q109296882 S248 Q56145673 /* 若 약 new */
Q87586836 P5537 Q56423271 S248 Q56145673 /* 羕 양 new */
Q87585965 P5537 Q109297238 S248 Q56145673 /* 嵃 언 new */
Q87586176 P5537 Q109297252 S248 Q56145673 /* 掩 엄 new */
Q87586426 P5537 Q109297252 S248 Q56145673 /* 淹 엄 new */
Q87586036 P5537 Q56216969 S248 Q56145673 /* 舁 여 new */
Q87586373 P5537 Q56217078 S248 Q56145673 /* 沿 연 new */
Q87586145 P5537 Q56217078 S248 Q56145673 /* 捐 연 new */
Q87586075 P5537 Q56217078 S248 Q56145673 /* 悁 연 new */
Q87586445 P5537 Q109300251 S248 Q56145673 /* 瀛 영 new */
Q87586937 P5537 Q109300251 S248 Q56145673 /* 荣 영 new */
Q87585885 P5537 Q56224461 S248 Q56145673 /* 娛 오 new */
Q87586943 P5537 Q56224461 S248 Q56145673 /* 茣 오 new */
Q87587238 P5537 Q109300481 S248 Q56145673 /* 馧 온 new */
Q87586746 P5537 Q109300481 S248 Q56145673 /* 穏 온 new */
Q87586227 P5537 Q109300485 S248 Q56145673 /* 㬈 올 new */
Q87586594 P5537 Q56236018 S248 Q56145673 /* 王 왕 new */
Q87585908 P5537 Q55808363 S248 Q56145673 /* 嬈 요 new */
Q87585809 P5537 Q55808363 S248 Q56145673 /* 嗂 요 new */
Q87586313 P5537 Q55808363 S248 Q56145673 /* 榣 요 new */
Q87585701 P5537 Q109301135 S248 Q56145673 /* 勇 용 new */
Q87585658 P5537 Q109301135 S248 Q56145673 /* 冗 용 new */
Q87586909 P5537 Q55809436 S248 Q56145673 /* 芋 우 new */
Q87586137 P5537 Q55809436 S248 Q56145673 /* 扝 우 new */
Q87587194 P5537 Q109301292 S248 Q56145673 /* 霣 운 new */
Q87587026 P5537 Q109301292 S248 Q56145673 /* 蝹 운 new */
Q87585660 P5537 Q56248936 S248 Q56145673 /* 冤 원 new */
Q87585922 P5537 Q56248936 S248 Q56145673 /* 寃 원 new */
Q87586615 P5537 Q56098735 S248 Q56145673 /* 瑜 유 new */
Q87587089 P5537 Q56098735 S248 Q56145673 /* 諭 유 new */
Q87586983 P5537 Q56098735 S248 Q56145673 /* 蕤 유 new */
Q87586630 P5537 Q56098735 S248 Q56145673 /* 甤 유 new */
Q87586647 P5537 Q56098735 S248 Q56145673 /* 瘐 유 new */
Q87586868 P5537 Q109302342 S248 Q56145673 /* 育 육 new */
Q87587052 P5537 Q56224462 S248 Q56145673 /* 衣 의 new */
Q87586640 P5537 Q56224459 S248 Q56145673 /* 異 이 new */
Q87586066 P5537 Q56248650 S248 Q56145673 /* 忍 인 new */
Q87586412 P5537 Q56248650 S248 Q56145673 /* 湮 인 new */
Q87585680 P5537 Q56248650 S248 Q56145673 /* 刃 인 new */
Q87587078 P5537 Q109302946 S248 Q56145673 /* 䚾 임 new */
Q87586880 P5537 Q109302951 S248 Q56145673 /* 媵 잉 new */
Q87586843 P5537 Q56216549 S248 Q56145673 /* 者 자 new */
Q87586093 P5537 Q56216549 S248 Q56145673 /* 慈 자 new */
Q87586418 P5537 Q56216549 S248 Q56145673 /* 滋 자 new */
Q87586480 P5537 Q109303021 S248 Q56145673 /* 爵 작 new */
Q87585709 P5537 Q109303021 S248 Q56145673 /* 勺 작 new */
Q87585939 P5537 Q56237230 S248 Q56145673 /* 将 장 new */
Q87585829 P5537 Q56237230 S248 Q56145673 /* 壮 장 new */
Q87585652 P5537 Q56248937 S248 Q56145673 /* 再 재 new */
Q55738328 P5537 Q109303298 S248 Q56145673 /* 著 저 new */
Q87586772 P5537 Q56238510 S248 Q56145673 /* 篆 전 new */
Q87585827 P5537 Q109303444 S248 Q56145673 /* 切 절 new */
Q87587030 P5537 Q109303454 S248 Q56145673 /* 蜨 접 new */
Q87585776 P5537 Q56170336 S248 Q56145673 /* 呈 정 new */
Q87586441 P5537 Q56170336 S248 Q56145673 /* 瀞 정 new */
Q87586430 P5537 Q56216740 S248 Q56145673 /* 潮 조 new */
Q87586722 P5537 Q56216740 S248 Q56145673 /* 祖 조 new */
Q87586058 P5537 Q56216740 S248 Q56145673 /* 彫 조 new */
Q87585778 P5537 Q56216730 S248 Q56145673 /* 周 주 new */
Q87585733 P5537 Q109304638 S248 Q56145673 /* 卽 즉 new */
Q87585731 P5537 Q109304638 S248 Q56145673 /* 即 즉 new */
Q87586325 P5537 Q109304657 S248 Q56145673 /* 櫛 즐 new */
Q87586110 P5537 Q109304671 S248 Q56145673 /* 憎 증 new */
Q87586071 P5537 Q56098741 S248 Q56145673 /* 志 지 new */
Q87586915 P5537 Q56098741 S248 Q56145673 /* 芝 지 new */
Q87586666 P5537 Q109305009 S248 Q56145673 /* 直 직 new */
Q87586683 P5537 Q56635439 S248 Q56145673 /* 眞 진 new */
Q87586215 P5537 Q56635439 S248 Q56145673 /* 晉 진 new */
Q87586617 P5537 Q56635439 S248 Q56145673 /* 瑱 진 new */
Q87586169 P5537 Q56635439 S248 Q56145673 /* 搢 진 new */
Q87586698 P5537 Q56635439 S248 Q56145673 /* 瞋 진 new */
Q87587255 P5537 Q56635439 S248 Q56145673 /* 鬒 진 new */
Q87586421 P5537 Q56635439 S248 Q56145673 /* 滇 진 new */
Q87586687 P5537 Q56635439 S248 Q56145673 /* 真 진 new */
Q87585764 P5537 Q109305282 S248 Q56145673 /* 叱 질 new */
Q87586126 P5537 Q109305295 S248 Q56145673 /* 懲 징 new */
Q87586331 P5537 Q109306894 S248 Q56145673 /* 次 차 new */
Q87586476 P5537 Q109306911 S248 Q56145673 /* 爨 찬 new */
Q87586121 P5537 Q109306956 S248 Q56145673 /* 憯 참 new */
Q87586962 P5537 Q109307000 S248 Q56145673 /* 菜 채 new */
Q87586936 P5537 Q109307000 S248 Q56145673 /* 茝 채 new */
Q87586449 P5537 Q109307117 S248 Q56145673 /* 灊 첨 new */
Q87585827 P5537 Q109307188 S248 Q56145673 /* 切 체 new */
Q87586857 P5537 Q109307310 S248 Q56145673 /* 聰 총 new */
Q87586241 P5537 Q109307375 S248 Q56145673 /* 最 최 new */
Q87586774 P5537 Q109307433 S248 Q56145673 /* 築 축 new */
Q87586734 P5537 Q109307440 S248 Q56145673 /* 秫 출 new */
Q87586809 P5537 Q109307737 S248 Q56145673 /* 緇 치 new */
Q87587013 P5537 Q109307737 S248 Q56145673 /* 蚩 치 new */
Q87585925 P5537 Q109307737 S248 Q56145673 /* 寘 치 new */
Q87586397 P5537 Q109307778 S248 Q56145673 /* 浸 침 new */
Q87586456 P5537 Q109308495 S248 Q56145673 /* 炭 탄 new */
Q87585813 P5537 Q109308495 S248 Q56145673 /* 嘆 탄 new */
Q87585890 P5537 Q109308520 S248 Q56145673 /* 娧 태 new */
Q87586384 P5537 Q59661943 S248 Q56145673 /* 派 파 new */
Q87586973 P5537 Q109309530 S248 Q56145673 /* 蓱 평 new */
Q87586141 P5537 Q109309565 S248 Q56145673 /* 抱 포 new */
Q87585714 P5537 Q109309565 S248 Q56145673 /* 包 포 new */
Q87586268 P5537 Q109309849 S248 Q56145673 /* 杓 표 new */
Q87587205 P5537 Q109310146 S248 Q56145673 /* 韠 필 new */
Q87585693 P5537 Q109310233 S248 Q56145673 /* 割 할 new */
Q87585793 P5537 Q109310243 S248 Q56145673 /* 啣 함 new */
Q87586410 P5537 Q109310265 S248 Q56145673 /* 港 항 new */
Q55846088 P5537 Q55808338 S248 Q56145673 /* 海 해 new */
Q87586338 P5537 Q109310420 S248 Q56145673 /* 歔 허 new */
Q87586113 P5537 Q109310426 S248 Q56145673 /* 憲 헌 new */
Q87587163 P5537 Q109316433 S248 Q56145673 /* 鋗 현 new */
Q87586053 P5537 Q63247695 S248 Q56145673 /* 形 형 new */
Q87585840 P5537 Q63247695 S248 Q56145673 /* 型 형 new */
Q87586393 P5537 Q56171502 S248 Q56145673 /* 浩 호 new */
Q87586921 P5537 Q56677153 S248 Q56145673 /* 花 화 new */
Q87585604 P5537 Q109317051 S248 Q56145673 /* 丸 환 new */
Q87586095 P5537 Q109317070 S248 Q56145673 /* 慌 황 new */
Q87586084 P5537 Q109317108 S248 Q56145673 /* 悔 회 new */
Q87586909 P5537 Q109317263 S248 Q56145673 /* 芋 후 new */
Q87585800 P5537 Q109317423 S248 Q56145673 /* 喙 훼 new */
Q87585724 P5537 Q109317423 S248 Q56145673 /* 卉 훼 new */
Q87586187 P5537 Q109317466 S248 Q56145673 /* 撝 휘 new */
Q87587007 P5537 Q109317504 S248 Q56145673 /* 虧 휴 new */
Q87585774 P5537 Q109317937 S248 Q56145673 /* 吸 흡 new */
Q87585882 P5537 Q109317951 S248 Q56145673 /* 姬 희 new */
</pre>
pg6ftobb4hhp1omke7bik53apoim0pb
Template:Cite bla
10
178441
762156
2026-09-18T11:08:16Z
Christoph Jauera (WMDE)
29989
Created page with "{{{year}}}"
762156
wikitext
text/x-wiki
{{{year}}}
luxm7ldfhmhjozg4eqfq5cxe9iiqz54
Wikipedia:Sandbox/MoveIt moved 2026-09-18T11-10-09-874Z
4
178442
762157
2026-09-18T11:10:10Z
Closed Limelike Curves
60396
MoveIt live rename test: creating the page to be renamed
762157
wikitext
text/x-wiki
Throwaway page for the Move It live rename test (2026-09-18T11-10-09-874Z). Safe to delete.
9rejnd2dul62y8czs09x4wunxx2hmib
762158
762157
2026-09-18T11:10:12Z
Closed Limelike Curves
60396
Closed Limelike Curves moved page [[Wikipedia:Sandbox/MoveIt move 2026-09-18T11-10-09-874Z]] to [[Wikipedia:Sandbox/MoveIt moved 2026-09-18T11-10-09-874Z]]: Move It live rename test (via Move It browser extension)
762157
wikitext
text/x-wiki
Throwaway page for the Move It live rename test (2026-09-18T11-10-09-874Z). Safe to delete.
9rejnd2dul62y8czs09x4wunxx2hmib
762161
762158
2026-09-18T11:10:14Z
Closed Limelike Curves
60396
MoveIt live rename test teardown
762161
wikitext
text/x-wiki
phoiac9h4m842xq45sp7s6u21eteeq1
Wikipedia:Sandbox/MoveIt move 2026-09-18T11-10-09-874Z
4
178443
762159
2026-09-18T11:10:12Z
Closed Limelike Curves
60396
Closed Limelike Curves moved page [[Wikipedia:Sandbox/MoveIt move 2026-09-18T11-10-09-874Z]] to [[Wikipedia:Sandbox/MoveIt moved 2026-09-18T11-10-09-874Z]]: Move It live rename test (via Move It browser extension)
762159
wikitext
text/x-wiki
#REDIRECT [[Wikipedia:Sandbox/MoveIt moved 2026-09-18T11-10-09-874Z]]
{{Redirect category shell|
{{R from move}}
}}
deb3m227azpnk1wcj98yuaf6n6wp7m0
762160
762159
2026-09-18T11:10:13Z
Closed Limelike Curves
60396
MoveIt live rename test teardown
762160
wikitext
text/x-wiki
phoiac9h4m842xq45sp7s6u21eteeq1
User:Ioannis Kouimoutzoglou/sandbox
2
178444
762163
2026-09-18T11:47:40Z
Cabayi
3052
Cabayi moved page [[User:Ioannis Kouimoutzoglou/sandbox]] to [[User:Qooimi/sandbox]]: Automatically moved page while renaming the user "[[Special:CentralAuth/Ioannis Kouimoutzoglou|Ioannis Kouimoutzoglou]]" to "[[Special:CentralAuth/Qooimi|Qooimi]]"
762163
wikitext
text/x-wiki
#REDIRECT [[User:Qooimi/sandbox]]
{{Redirect category shell|
{{R from move}}
}}
k0o9hsve8mjjpl48gomkhj67vmymgof