Wikipedia testwiki https://test.wikipedia.org/wiki/Main_Page MediaWiki 1.48.0-wmf.1 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 769814 769519 2026-10-22T22:20:20Z ~2026-56454-78 76373 /* Test */ Start 769814 wikitext text/x-wiki = Test = 1022 Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control (Mostly 6/23) and until 24 Restriction until no edits made all day, Use Account Sometimes. Up To Date 2:6 — 10:8, 242 days, (10:9+ to fill out). *10:9, 10:10, 10:11, 10:12, 10:13 (?) *10:14 (?) *10:15 (?) *10:16 (?) *10:17 (?) *10:18 (?) *10:19 (10:20) ''10:21'' *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. *202 6826, Cans of Coca Cola, Lime Cordial, Milk and Others. *202 6827, Blankets, Pillows, Circle Table and Others. *202 6828, Grated Cheese, Scissors, Knifes and Forks and Others. *202 6829, Cans of Coca Cola, Bottles, Waters, Milk and Others. *202 6830, Plates, Stand, Frypans and Others. *202 6831, Metal Things, Water Bottles, Cans of Coca Cola and Others. *202 6901, Aldi Bag with Stuff or Aprons. *202 6902, Food Shopping like Cola Bottles, Cheese with Nachos and Others. *202 6903, Mask Perfumes, Soaps and Others. *202 6904, Baskets, Battery Pack, Pillows or Lasagna and Others *202 6905, Frypans, Lids, Tablemats and Others. *202 6906, Fathers Day Presents, Glasses, Bags and Others. *202 6907, Deep Heat, Scissors, Milo or Container and Others. *202 6908, Baskets, Coathanger, Blankets and Others. *202 6909, Container Biscuit, Pastas or Pans. *202 6910, Food Shopping like Milks, M&Ms, Sauces, Coca Cola Cans and Others. *202 6911, Pillows, Dressing Gowns, Extra Mint and Others. *202 6912, Laundry Stuff like boxes, bags or Dad's Wrist and Others. *202 6913, Grater Stuff, Pans and Others. *202 6914, Bottles of Cola, Breads, Milk to make Chocolate. *202 6915, Iced Coffee, Water Bottles, Baskets and Others. *202 6916, Aldi Bag, Strawberry Mints and Others. *202 6917, Lighters, Plates, Freshener or Spray and Others. *202 6918, New Clothes, Basket, Extra Mint and Others. *202 6919, Face Cloths, Lu Paper, Water and Others. *202 6920, Domino's Pizza, Pillows, Notes and Others. *202 6921, Remotes, Pizza and Barbecue Shapes, Square Pillow and Others. *202 6922, Food Shopping like Waters, Cans of Coca Cola, Cheese, Lasagna and Others. *202 6923, Cloths, Facecloth, New Pot and Others. *202 6924, Aldi Stuff, Glass Cups, Candles and Others. *202 6925, Copy Paper, Glasses, Lasagna Tray Pan and Others. *202 6926, Tax Boxes, Bags, Lighter, Texter and Others. *202 6927, Cans of Coca Cola, Bottles, Cordial and Others. *202 6928, Pairs of Shoes or Slippers, Square Pillow and Others. *202 6929, Big Spoon and Others. *202 6930, Cola Bottle and Others. *202 61001, Yellow Bag and Others. *202 61002, Coathangers or Towels and Others. *202 61003, Knives, Forks and Others. *202 61004, Hats like DNA hat and Others. *202 61005, Pizza SHAPES and Others. *202 61006, Old Pillow or Cola and Others. Current, 202 61007. ($#!+). *202 61008. (High Speed Railway, Train) ''20261009'' 77iqrsrk63g7x8kc863wlf9jruvhkgv 769815 769814 2026-10-22T22:20:44Z ~2026-56454-78 76373 769815 wikitext text/x-wiki = Test = 1022 - Lemon Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control (Mostly 6/23) and until 24 Restriction until no edits made all day, Use Account Sometimes. Up To Date 2:6 — 10:8, 242 days, (10:9+ to fill out). *10:9, 10:10, 10:11, 10:12, 10:13 (?) *10:14 (?) *10:15 (?) *10:16 (?) *10:17 (?) *10:18 (?) *10:19 (10:20) ''10:21'' *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. *202 6826, Cans of Coca Cola, Lime Cordial, Milk and Others. *202 6827, Blankets, Pillows, Circle Table and Others. *202 6828, Grated Cheese, Scissors, Knifes and Forks and Others. *202 6829, Cans of Coca Cola, Bottles, Waters, Milk and Others. *202 6830, Plates, Stand, Frypans and Others. *202 6831, Metal Things, Water Bottles, Cans of Coca Cola and Others. *202 6901, Aldi Bag with Stuff or Aprons. *202 6902, Food Shopping like Cola Bottles, Cheese with Nachos and Others. *202 6903, Mask Perfumes, Soaps and Others. *202 6904, Baskets, Battery Pack, Pillows or Lasagna and Others *202 6905, Frypans, Lids, Tablemats and Others. *202 6906, Fathers Day Presents, Glasses, Bags and Others. *202 6907, Deep Heat, Scissors, Milo or Container and Others. *202 6908, Baskets, Coathanger, Blankets and Others. *202 6909, Container Biscuit, Pastas or Pans. *202 6910, Food Shopping like Milks, M&Ms, Sauces, Coca Cola Cans and Others. *202 6911, Pillows, Dressing Gowns, Extra Mint and Others. *202 6912, Laundry Stuff like boxes, bags or Dad's Wrist and Others. *202 6913, Grater Stuff, Pans and Others. *202 6914, Bottles of Cola, Breads, Milk to make Chocolate. *202 6915, Iced Coffee, Water Bottles, Baskets and Others. *202 6916, Aldi Bag, Strawberry Mints and Others. *202 6917, Lighters, Plates, Freshener or Spray and Others. *202 6918, New Clothes, Basket, Extra Mint and Others. *202 6919, Face Cloths, Lu Paper, Water and Others. *202 6920, Domino's Pizza, Pillows, Notes and Others. *202 6921, Remotes, Pizza and Barbecue Shapes, Square Pillow and Others. *202 6922, Food Shopping like Waters, Cans of Coca Cola, Cheese, Lasagna and Others. *202 6923, Cloths, Facecloth, New Pot and Others. *202 6924, Aldi Stuff, Glass Cups, Candles and Others. *202 6925, Copy Paper, Glasses, Lasagna Tray Pan and Others. *202 6926, Tax Boxes, Bags, Lighter, Texter and Others. *202 6927, Cans of Coca Cola, Bottles, Cordial and Others. *202 6928, Pairs of Shoes or Slippers, Square Pillow and Others. *202 6929, Big Spoon and Others. *202 6930, Cola Bottle and Others. *202 61001, Yellow Bag and Others. *202 61002, Coathangers or Towels and Others. *202 61003, Knives, Forks and Others. *202 61004, Hats like DNA hat and Others. *202 61005, Pizza SHAPES and Others. *202 61006, Old Pillow or Cola and Others. Current, 202 61007. ($#!+). *202 61008. (High Speed Railway, Train) ''20261009'' s7x4bjimqvrmyhov2fvx11ljh3d3h2v 769816 769815 2026-10-22T22:21:41Z ~2026-56454-78 76373 769816 wikitext text/x-wiki = Test = 1022 - Lemon Juices Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control (Mostly 6/23) and until 24 Restriction until no edits made all day, Use Account Sometimes. Up To Date 2:6 — 10:8, 242 days, (10:9+ to fill out). *10:9, 10:10, 10:11, 10:12, 10:13 (?) *10:14 (?) *10:15 (?) *10:16 (?) *10:17 (?) *10:18 (?) *10:19 (10:20) ''10:21'' *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. *202 6826, Cans of Coca Cola, Lime Cordial, Milk and Others. *202 6827, Blankets, Pillows, Circle Table and Others. *202 6828, Grated Cheese, Scissors, Knifes and Forks and Others. *202 6829, Cans of Coca Cola, Bottles, Waters, Milk and Others. *202 6830, Plates, Stand, Frypans and Others. *202 6831, Metal Things, Water Bottles, Cans of Coca Cola and Others. *202 6901, Aldi Bag with Stuff or Aprons. *202 6902, Food Shopping like Cola Bottles, Cheese with Nachos and Others. *202 6903, Mask Perfumes, Soaps and Others. *202 6904, Baskets, Battery Pack, Pillows or Lasagna and Others *202 6905, Frypans, Lids, Tablemats and Others. *202 6906, Fathers Day Presents, Glasses, Bags and Others. *202 6907, Deep Heat, Scissors, Milo or Container and Others. *202 6908, Baskets, Coathanger, Blankets and Others. *202 6909, Container Biscuit, Pastas or Pans. *202 6910, Food Shopping like Milks, M&Ms, Sauces, Coca Cola Cans and Others. *202 6911, Pillows, Dressing Gowns, Extra Mint and Others. *202 6912, Laundry Stuff like boxes, bags or Dad's Wrist and Others. *202 6913, Grater Stuff, Pans and Others. *202 6914, Bottles of Cola, Breads, Milk to make Chocolate. *202 6915, Iced Coffee, Water Bottles, Baskets and Others. *202 6916, Aldi Bag, Strawberry Mints and Others. *202 6917, Lighters, Plates, Freshener or Spray and Others. *202 6918, New Clothes, Basket, Extra Mint and Others. *202 6919, Face Cloths, Lu Paper, Water and Others. *202 6920, Domino's Pizza, Pillows, Notes and Others. *202 6921, Remotes, Pizza and Barbecue Shapes, Square Pillow and Others. *202 6922, Food Shopping like Waters, Cans of Coca Cola, Cheese, Lasagna and Others. *202 6923, Cloths, Facecloth, New Pot and Others. *202 6924, Aldi Stuff, Glass Cups, Candles and Others. *202 6925, Copy Paper, Glasses, Lasagna Tray Pan and Others. *202 6926, Tax Boxes, Bags, Lighter, Texter and Others. *202 6927, Cans of Coca Cola, Bottles, Cordial and Others. *202 6928, Pairs of Shoes or Slippers, Square Pillow and Others. *202 6929, Big Spoon and Others. *202 6930, Cola Bottle and Others. *202 61001, Yellow Bag and Others. *202 61002, Coathangers or Towels and Others. *202 61003, Knives, Forks and Others. *202 61004, Hats like DNA hat and Others. *202 61005, Pizza SHAPES and Others. *202 61006, Old Pillow or Cola and Others. Current, 202 61007. ($#!+). *202 61008. (High Speed Railway, Train) ''20261009'' 8f6pafh4jdnq980mm0mwyp6p2ezmspc 769817 769816 2026-10-22T22:22:09Z ~2026-56454-78 76373 769817 wikitext text/x-wiki = Test = 1022 - Lemon Juices, Seeds Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control (Mostly 6/23) and until 24 Restriction until no edits made all day, Use Account Sometimes. Up To Date 2:6 — 10:8, 242 days, (10:9+ to fill out). *10:9, 10:10, 10:11, 10:12, 10:13 (?) *10:14 (?) *10:15 (?) *10:16 (?) *10:17 (?) *10:18 (?) *10:19 (10:20) ''10:21'' *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. *202 6826, Cans of Coca Cola, Lime Cordial, Milk and Others. *202 6827, Blankets, Pillows, Circle Table and Others. *202 6828, Grated Cheese, Scissors, Knifes and Forks and Others. *202 6829, Cans of Coca Cola, Bottles, Waters, Milk and Others. *202 6830, Plates, Stand, Frypans and Others. *202 6831, Metal Things, Water Bottles, Cans of Coca Cola and Others. *202 6901, Aldi Bag with Stuff or Aprons. *202 6902, Food Shopping like Cola Bottles, Cheese with Nachos and Others. *202 6903, Mask Perfumes, Soaps and Others. *202 6904, Baskets, Battery Pack, Pillows or Lasagna and Others *202 6905, Frypans, Lids, Tablemats and Others. *202 6906, Fathers Day Presents, Glasses, Bags and Others. *202 6907, Deep Heat, Scissors, Milo or Container and Others. *202 6908, Baskets, Coathanger, Blankets and Others. *202 6909, Container Biscuit, Pastas or Pans. *202 6910, Food Shopping like Milks, M&Ms, Sauces, Coca Cola Cans and Others. *202 6911, Pillows, Dressing Gowns, Extra Mint and Others. *202 6912, Laundry Stuff like boxes, bags or Dad's Wrist and Others. *202 6913, Grater Stuff, Pans and Others. *202 6914, Bottles of Cola, Breads, Milk to make Chocolate. *202 6915, Iced Coffee, Water Bottles, Baskets and Others. *202 6916, Aldi Bag, Strawberry Mints and Others. *202 6917, Lighters, Plates, Freshener or Spray and Others. *202 6918, New Clothes, Basket, Extra Mint and Others. *202 6919, Face Cloths, Lu Paper, Water and Others. *202 6920, Domino's Pizza, Pillows, Notes and Others. *202 6921, Remotes, Pizza and Barbecue Shapes, Square Pillow and Others. *202 6922, Food Shopping like Waters, Cans of Coca Cola, Cheese, Lasagna and Others. *202 6923, Cloths, Facecloth, New Pot and Others. *202 6924, Aldi Stuff, Glass Cups, Candles and Others. *202 6925, Copy Paper, Glasses, Lasagna Tray Pan and Others. *202 6926, Tax Boxes, Bags, Lighter, Texter and Others. *202 6927, Cans of Coca Cola, Bottles, Cordial and Others. *202 6928, Pairs of Shoes or Slippers, Square Pillow and Others. *202 6929, Big Spoon and Others. *202 6930, Cola Bottle and Others. *202 61001, Yellow Bag and Others. *202 61002, Coathangers or Towels and Others. *202 61003, Knives, Forks and Others. *202 61004, Hats like DNA hat and Others. *202 61005, Pizza SHAPES and Others. *202 61006, Old Pillow or Cola and Others. Current, 202 61007. ($#!+). *202 61008. (High Speed Railway, Train) ''20261009'' a46qc2mnmj3sickeytsq6y9qtdk8kcd 769818 769817 2026-10-22T22:22:45Z ~2026-56454-78 76373 /* Test */ Done, 5 More Days Tomorrow 769818 wikitext text/x-wiki = Test = 1022 - Lemon Juices, Seeds Candy Crush Saga Wiki: Tasty Sugar Track Edits Is Out Of Control (Mostly 6/23) and until 24 Restriction until no edits made all day, Use Account Sometimes. Up To Date 2:6 — 10:8, 242 days, (10:9+ to fill out). *10:9, 10:10, 10:11, 10:12, 10:13 (?) *10:14 (?) *10:15 (?) *10:16 (?) *10:17 (?) *10:18 (?) *10:19 (?) *10:20 (10:21) ''10:22'' *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. *202 6826, Cans of Coca Cola, Lime Cordial, Milk and Others. *202 6827, Blankets, Pillows, Circle Table and Others. *202 6828, Grated Cheese, Scissors, Knifes and Forks and Others. *202 6829, Cans of Coca Cola, Bottles, Waters, Milk and Others. *202 6830, Plates, Stand, Frypans and Others. *202 6831, Metal Things, Water Bottles, Cans of Coca Cola and Others. *202 6901, Aldi Bag with Stuff or Aprons. *202 6902, Food Shopping like Cola Bottles, Cheese with Nachos and Others. *202 6903, Mask Perfumes, Soaps and Others. *202 6904, Baskets, Battery Pack, Pillows or Lasagna and Others *202 6905, Frypans, Lids, Tablemats and Others. *202 6906, Fathers Day Presents, Glasses, Bags and Others. *202 6907, Deep Heat, Scissors, Milo or Container and Others. *202 6908, Baskets, Coathanger, Blankets and Others. *202 6909, Container Biscuit, Pastas or Pans. *202 6910, Food Shopping like Milks, M&Ms, Sauces, Coca Cola Cans and Others. *202 6911, Pillows, Dressing Gowns, Extra Mint and Others. *202 6912, Laundry Stuff like boxes, bags or Dad's Wrist and Others. *202 6913, Grater Stuff, Pans and Others. *202 6914, Bottles of Cola, Breads, Milk to make Chocolate. *202 6915, Iced Coffee, Water Bottles, Baskets and Others. *202 6916, Aldi Bag, Strawberry Mints and Others. *202 6917, Lighters, Plates, Freshener or Spray and Others. *202 6918, New Clothes, Basket, Extra Mint and Others. *202 6919, Face Cloths, Lu Paper, Water and Others. *202 6920, Domino's Pizza, Pillows, Notes and Others. *202 6921, Remotes, Pizza and Barbecue Shapes, Square Pillow and Others. *202 6922, Food Shopping like Waters, Cans of Coca Cola, Cheese, Lasagna and Others. *202 6923, Cloths, Facecloth, New Pot and Others. *202 6924, Aldi Stuff, Glass Cups, Candles and Others. *202 6925, Copy Paper, Glasses, Lasagna Tray Pan and Others. *202 6926, Tax Boxes, Bags, Lighter, Texter and Others. *202 6927, Cans of Coca Cola, Bottles, Cordial and Others. *202 6928, Pairs of Shoes or Slippers, Square Pillow and Others. *202 6929, Big Spoon and Others. *202 6930, Cola Bottle and Others. *202 61001, Yellow Bag and Others. *202 61002, Coathangers or Towels and Others. *202 61003, Knives, Forks and Others. *202 61004, Hats like DNA hat and Others. *202 61005, Pizza SHAPES and Others. *202 61006, Old Pillow or Cola and Others. Current, 202 61007. ($#!+). *202 61008. (High Speed Railway, Train) ''20261009'' 8qg7j3epqble5x2bp2qzfmbpp3uyzx0 User:John Vandenberg/async test write 2 81547 769755 769381 2026-10-22T13:06:09Z Pywikibot-test 23124 Pywikibot 11.10.0.dev0 769755 wikitext text/x-wiki 1792674360.2784016 rbo105ndjoyqog56swddtjxcnsi6x2m User:John Vandenberg/appendtext test 2 81788 769754 769380 2026-10-22T13:05:59Z Pywikibot-test 23124 769754 wikitext text/x-wiki 1433650768.531433650922.331433651729.111433670166.311433675620.231434189298.391434190713.181434466819.82218051434544025.22135851434556196.60172341435173199.59346151435175699.59451271435227022.74044541435528701.75742911435530425.45590261435603389.080081437231694.72999551437247968.58793571437249806.3797741437298795.05681351437299498.54262071437301447.66920381437302227.7655441437303194.27986031437304101.72397661437310188.7074311437310950.0167771437312161.48824671437313010.34581731437313729.64502261437508795.02368621437509778.81783961437516631.40031891438256915.00195531438380338.75435851438383980.68647171438454064.30758831438457192.55998851438473558.4497151438475370.52737021438888563.82252121439048615.09364531439242551.86522051439284878.94054751439567068.00147221439645869.40761881439653355.34343361439892097.89366271439893989.92894151439937872.74017361439942911.25551271440071096.08264111440280762.25626281440718001.3262011440893319.42683861441040710.94389411441045094.56088661441367039.71286131441492543.00856571441494238.9647241443131370.03606581443212814.54482251454969098.621455143085.01455479939.331458010578.141667865282.52259731667886777.04896881667890384.16996771667891590.83226851667893076.91738251667895853.758761667903064.99619671667923005.8748951667928572.68390731667933784.59484671667953902.59001061667977923.4422121667980794.38768461667998421.35940931668010265.61172651668017452.821981668037264.28078271668060176.7066241668064765.02555161668074805.6843691668086298.94039751668146229.9122951668195362.96826151668202976.2808351668237144.36446861668334598.07503751668351702.72978881668355273.88250331668365870.03056961668380539.2045151668413384.79889971668425433.20089171668429428.62591481668429882.60904881668457667.70654341668457670.14254471668489259.42919141668489272.77256321668524787.90621761668619093.49428681668627855.24322251668715685.06132861668752284.64053461668846412.18063191668859062.45581651668861871.6680541668863624.53730581668906968.63125281668968346.827691669010411.7630731669034060.6490591669034135.1873461669111400.3310911669112565.91641261669115243.3388661669117792.36109231669147328.09415841669202489.4733361669207650.32954051669293250.78917381669293379.89944481669376126.44172071669383245.76502471669390928.33843281669456758.37305931669460552.29366331669466891.97368241669468483.16195921669507139.0193781669555832.00191161669561735.99639271669567236.94770341669575598.18926261669583250.82441161669589277.69016361669617066.74746061669623772.9824791669639778.26535651669648369.11541911669681417.00446221669694451.18411281669752632.77524021669790924.5213481669793446.41492681669806912.04391981669824036.82929231669872027.60449481669898227.71295671669898259.26809931669921155.98349361670061183.07913141670066507.8165841670077709.53290721670095550.83527471670107627.98861271670121136.95061851670138654.99623131670200104.08187131670230755.3226831670244520.57672931670244668.51782011670389975.82026081670390023.37481831670437142.29134321670474770.88995531670487246.87528041670502115.00278231670502920.1938131670847688.62029081670848465.75781231670851705.87951061671033970.25642091671040035.06844951671042864.6599261671372985.38839651671380314.9132991671397640.27274011671414714.3057121671436644.76151321671464740.28983191671471979.49879741671515351.36315011671534919.43988371671552136.73949381671567767.751751671633257.00196431671770826.36481481671831280.1013831671880464.16703251671892132.39851621671894047.95178441671895309.44157341671909181.81563191671915314.86987641671958262.78592091671964901.68418721672000091.18395731672040310.53217081672050418.50751851672064946.23232941672111553.61295031672117635.92343691672130442.62549381672242689.61853311672316734.83227941672317602.87131831672393398.53247791672410436.25166461672524792.27631931672607847.59926841672644463.87349151672646823.01231341672662689.7048611672663480.46076921672679608.50131681672683539.08552241672699544.1003541672732083.7852531672738571.41738751672756132.6532181672773164.29544851672819542.08460331672825014.19517781672905848.38628651672913462.50501871672919738.71067861672922430.75280711672923322.11899111672931497.2450511672932304.1778181672945954.7680341673031863.65857821673079844.9389911673088359.9833371673095552.19145581673097227.50064781673102532.33062361673103474.52100591673115502.80200391673170728.81979011673180084.83551031673186706.26281071673193236.3913051673204572.94682721673251372.26334931673257873.80217721673265157.1539221673268011.07930541673273333.41361331673278687.03390881673326768.0135041673336643.46683241673377550.0737211673406497.31679181673429347.03616951673442396.44323591673462031.40780231673475642.46197681673486662.78692481673494604.4536731673538992.12018081673597172.3338311673607749.57159781673612477.3083471673784155.33494331673792254.69903181673797192.45269541673805036.33327221673809787.90321951673820123.49186471673828737.7350961673845480.29922721673867388.29650971673871721.06576231673872705.55981831673881096.00600361673886092.39976671673901527.23546221673936700.1277911674024723.59655931674029565.17511731674112677.72348791674131134.36896941674131931.51858191674176788.94118571674205022.57874321674205892.4945881674207066.500241674237874.79511361674292792.7148671674300054.9405991674302649.25306581674315023.03331971674321156.4278271674330147.9499351674375033.1853471674379973.83156511674405785.2695661674460497.39998821674590174.95085531674599728.517341674918001.6330231674933771.13804131674942945.7791681674948667.64437911674994582.97465441675031208.62388441675082059.0771621675082116.2687371675107052.030031675108612.33305431675125215.25636861675257210.1793411675341484.38473531675341609.7052491675405564.5855741675453239.69066831675497461.10145021675528556.1533341675609308.2208911675687010.83857871675687111.48495861675814393.79852651675946118.90168211675946263.62637621676270319.42003041676413416.73733331676415638.60224561676550944.72917251676550988.86583191676811844.2470331676892937.27954441677156006.10806781677156012.4058921677404093.0326611677414534.3757681677422594.66884061677431827.26376751677502782.10921571677523601.2258471677532681.36643621677547559.68123271677665504.37648651677884342.66578171677941180.10126421677945698.08328151677946891.47642021678007696.49033051678013853.27689121678027514.350981678043805.73149591678052259.90557241678052643.0314441678106220.95231061678106343.42481541678133527.48043781678172110.71678571678365385.72825381678365409.99574831678764799.86219881678813325.91175081678813350.79962161679170545.65496781679450012.02785161679667672.31822281679744609.64862081679759956.30766031679761981.30153061679763749.89561941679767912.40684821679841243.24157331679932902.0535151679932917.83848141679940392.27980331679940406.82556631680053071.3510561680080183.73721581680082474.63970731680084259.96698951680086369.3228471680091872.83918521680118892.88375951680163589.5406531680163600.85161521680176046.1660681680176093.195821680203006.74859981680218432.4234941680218462.99551681680252349.87218141680259887.77778031680276784.21608421680363996.79403231680364030.12159371680461718.1685331680510128.81247231680523016.66201071680524491.84096381680535330.71197321680538614.16861461680540603.81350281680567879.27351781680584189.1618111680597522.02599571680611370.06081771680684863.62609741680702380.27745721680703768.80195071680724926.03246521680761509.16899231680781166.79312871680781181.85028271680802128.60378311680802968.58253961680810706.74496361680824056.68816421680858607.70792821680861050.77714251680866073.6807371680873834.65833931680876092.87447241680886191.0677981680893212.76874541680912955.40428971680931523.71085381680938348.89648771680946672.26258541680954488.31267331680957237.11845351680974132.6564441680981580.06852131680988103.15952011680998817.96175931681034799.03404331681040471.09055521681052004.54530671681126545.9002181681127117.2114981681132523.79209541681134369.85547611681139841.28229571681144411.1575561681148840.42879941681153937.74360161681160928.71128651681166905.73377011681187720.03183911681192405.11509941681227001.43019371681296338.53012781681298285.34920621681300548.25355361681399245.12391971681404166.32169871681450160.48757241681476226.65624211681482908.2132631681484907.63010051681488264.0226731681497922.02627541681516321.013621681550173.9751061681556873.35132771681634045.1093921681638556.73702431681643819.74579431681648142.90162351681654379.10618951681660670.91600231681663536.92180131681668105.8786741681697857.17983321681726412.36520551681728904.20325111681732377.95373061681732552.2726261681734122.47441771681739722.6026441681745392.19363141681752304.44942951681764534.25785851681834319.85117361681846787.53623871681860420.36393951681864973.31808471681875313.6030341681990891.22789741681990965.4691161682017923.75330021682021682.18149731682057250.76527521682059742.77901941682066226.93418961682076763.95251131682085198.28220251682144325.24995231682151599.1659521682171840.53873781682177076.96661421682183378.3197661682201845.24131771682207240.42407821682234649.83576371682237773.5109891682255562.43250821682256440.6314211682276533.21695041682307310.77357081682309188.4801751682327080.5300711682330112.66451981682335575.83368681682336670.2883251682364807.1775281682398596.78049471682412204.25284861682420579.50606181682438986.83246091682440038.89426971682460491.3521311682460514.15289761682486722.93688181682488779.60810041682526064.89231941682539359.5333161682594683.016191682595813.5718581682668022.43959161682669508.12358161682692147.2006271682757542.86185651682764905.5145551682772596.67823051682773643.5455011682784718.25319361682792198.62961861682846988.5308141682847360.08277031682855920.74403551682861011.37232731682866058.34553621682874046.51448271682874377.29042581682875782.05195261682880603.05094741682933872.46009541682935892.51180741682940017.87042071682941142.98671221682944638.7336221682968813.95042441683043013.224441683044388.7385881683079759.64020921683090931.4739611683122753.58097121683220168.91720751683220186.32398771683228402.15677021683229560.23437881683299138.82950661683545273.97475961683546542.5225811683639428.85272931683650636.34203671683805773.17751171683807026.16440961683929655.90975641683945251.3297731683945334.00193071683979199.57489941683989769.1559531684138199.31341811684138303.3588971684149417.94796661684150694.01225781684162796.8634221684166131.38370351684186491.90226461684251726.4504761684341513.18342381684408808.57671331684410199.48726771684489043.08548951684506392.8573881684675092.4285181684754267.71727821684755469.9380261684824482.14777731684830139.4911791684913767.22985341685013633.93379761685014938.77503231685102500.5862471685105187.50040251685186112.62153741685276024.9902461685359085.10708051685360365.34077381685452391.8990681685463350.18182641685464580.15679741685506240.55518721685507573.46218041685515091.31630541685618762.95992021685620191.40762351685686918.73273971685699127.00476841685700501.55954431685717478.4076761685734131.4306871685783480.31948381685784754.27991371685822284.17034241685826117.9924191685876410.60644561685899260.99922781685963819.95782521685965097.9749411686150851.77675581686223052.88230631686224433.3330841686232302.44289061686431729.6923871686484871.47790581686515043.2986561686569325.14197231686570601.30179381686829205.67923261686830619.36993621686858941.9247121686987477.50710231687163638.79776241687173445.39801721687174767.32710461687433296.5008811687434714.9197481687778668.3172251687780071.48142651687804721.06773691687804961.1013381687870703.48142171687880051.5818561687914862.05616451687945918.31335041687947395.06492521687953490.37763641687959324.18503831687975359.10666821687977529.40586021688005289.32374951688240380.11102061688282000.03003641688313546.3198141688475697.93261031688487946.15282921688516501.1861391688542375.87847381688542658.34382371688659572.67238471688989210.09367061689249540.64891221689516330.02128981689518572.78979041689583949.94965551689592901.34582541689607695.01970341689852040.93803671690180073.57848791690191138.51633981690321982.42092041690449914.8819191690455300.5934611690458478.94185231690465635.7540451690474689.47561761690539972.5845331690543686.42938161690568173.75836471690628964.38431071690634808.00196481690713940.84531521690740853.82095071690797462.8997041690802793.02018141690877446.66731241690889603.01329571690902576.47618631690960224.63360571690965952.47575381690985912.44080951690986558.72973781690988632.4453431691052503.35620671691059454.53480551691070774.57939621691155418.632231691252944.3855231691339134.81100341691400441.28892831691407321.69667531691432706.8650791691480503.51510481691481141.53991751691482868.38574171691653911.6456711691667067.58978751691677912.8174151691990311.52463151692012332.80747371692173850.40086171692259390.40197521692271662.9828511692354012.89279321692387939.37044841692450924.90117481692534492.76775311692541157.84960081692609941.4447311692613681.6871041692616885.06272461692862010.7047641692876369.23113751693053622.35440371693063667.55145881693149769.05626231693153142.6450571693216006.80971571693327074.38222051693400571.59087851693411769.74461581693475731.57202241693481027.00816321693491970.33835031693754058.26204921693826674.35946681694067456.52644161694086432.312941694086879.4216851694291429.4310971694431406.95781731694657927.28599861694659203.8303991694690891.68987661695036242.05242631695052511.6695451695073524.60868021695202102.93862631695206418.5803891695216347.58525681695221958.98424171695295594.74410271695320782.37095791695372272.756491695372628.97463751695378229.09218671695404004.23362351695634429.53836321695641055.01008581695761650.25719881695834309.91726141695927260.04524731695977453.164681695980141.0916121695994699.91543251696140618.86266831696336429.26674631696472860.44576241696505121.36730741696670716.8756681696689454.51658061696692541.47360921696850900.75192381697040191.60620881697097598.39965031697099236.2009691697144402.12478421697461393.63038371697527918.46235591697553804.78659531697815765.07235961697882531.84064671698051461.11684851698245633.10182791698508506.21113731698590537.26034331698771781.4928131698827472.40152741698827637.62499951698842362.84378241699091325.84301851699112379.118591699114243.11691121699184658.95015981699202708.55501941699205204.19041511699223592.85166761699283653.51198431699308697.88956881699632738.20176461699697040.08083271699706783.76506351699708540.52264861699878426.134871700605295.13594941700742428.27381941701453821.17849141701535213.18951851701596010.55240921701651782.60944631701676216.27204661701692980.01650791701786460.07426741701790394.30577541701794888.2957931701814293.08096051701829196.0474711701845925.83316681701848599.3431961701881057.82830721701954974.30711481701971095.83130741702043153.9835111702121022.79919271702122868.11675931702131140.8443211702209307.3005071702214096.37788411702297508.09620881702391057.6135691702476254.23142151702545723.33017161702556484.54818631702570523.91162061702584813.98265171702632851.84962561702767066.49533081702768384.77078131702786485.3929631702813757.61672471702976231.91704031702988046.03035161703007104.43871831703060641.49566441703061978.66786461703068432.47355061703161333.71216631703364778.24125841703400784.23487191703421297.88166571703422570.29016641703507209.10789851703681521.57480841703692553.249851703766399.7434331703852651.09494881703904819.15819121703906381.68961221703995904.11975221704121987.50157281704264435.08052851704282576.0567271704287308.40712621704298219.9210251704298836.44698121704303268.78285381704363509.4023921704370865.83305841704373191.9196831704446663.93405531704473306.82136271704556109.78341911704652663.27039841704703502.98144841705153078.2567631705171764.48118851705247919.4075471705321451.7373961705357661.07616421705461907.794251705752184.9362341705828818.60175251705830883.71437721705841015.54000781705844281.67964631705855451.01224971706185534.09338261706369476.87958551706371248.95242761706446636.12856911706448562.39597581706500837.33251021706622694.41761571706638400.31250291706643762.98329831706652657.88941431706698456.11485581706705858.3338771706775991.24169541706879091.59539581706959973.97395971706978466.78913071707041650.44565821707061227.6671281707135479.13930131707135774.83621931707138577.93408441707205349.07070681707210631.86285881707223177.35967421707234259.76761751707236462.89073851707298811.07813571707309485.17887141707324226.33939241707324395.90175751707324534.66345451707394969.43060231707473456.3788881707484017.54700971707509815.8565891707630003.67194221707650093.14672661707741016.75071951707843507.62747121707843972.63939711707891847.7828991707894042.62261721707894892.28781461708082572.46326521708270558.69651531708335825.3520781708343518.4265971708345382.65903431708346942.56566171708352754.41838361708355494.40021591708356544.03256871708357237.74094871708357678.17033841708523300.77632331708527433.11350181708597953.04801491708598048.15991881708600366.39798431708604576.4365961708610956.05604121708950178.1200671709014376.84691021709199311.14945361709209277.74335311709295953.42427751709372594.5523051709372731.93302561709372808.05139921709372973.60188251709374813.5571491709377109.42867421709484246.11830431709484785.2390241709533165.47048741709533819.17485741709534209.88706611709534926.47438381709538670.7195121709554858.88737061709556222.50437431709556406.85210971709564869.27713011709568887.47204641709573527.703281709629796.3196181709630611.95577671709630963.05990671709632191.8085871709632657.66816261709647467.98279861709660435.57397561709714867.27947381709717072.49129031709746877.2993021709805154.00563551709809459.23794721709814067.34054141709879953.99508521709884151.13086131709894214.31273981709902235.44790631709914532.75472951710159733.28755931710418921.42482541711628639.58727981711973782.74049451711974343.14418481711985794.7452041712014996.42285541712080693.69224641712155049.11888051712168399.60296921712169685.1040791712253703.75393061712502533.70237331712503293.1766331712505373.05488321712511056.70344231712511646.47766071712554342.8047431712578871.33526281712591147.02153471712593306.1449461712654643.9849731712672272.33918331712733238.39784071712773663.19977021712848308.0081541712860542.67349821713087332.46015721713121304.38284681713183849.22030931713372266.49107931713373136.88705831713417144.63786321713443071.2244371713541517.180411713541699.3184841713615294.52450591713619123.95877081713619984.8662581713620203.87909171713629353.7768171713693000.37563231713696953.16933941713701711.91550061713703518.66322571713708646.54834151713773912.73249241713776408.69481331713777146.3249111713784750.26938921713788549.0017581713803084.09800651713873378.93953251713874972.05580541713899910.39179831714006574.90925341714047778.38088851714214149.2920471714215604.62877371714218289.77900241714220302.95767071714231183.21794841714243696.78785441714305638.49526791714305731.21596931714311478.84540821714313996.51210671714485244.08302331714488946.5538881714652552.4470721714661325.34664131714665061.6320541714685108.3231281714709757.69277481714712589.13287451714717873.74175741714719260.34569121714908101.1871011714998038.7068751715004179.24228761715005017.33956381715011561.74028921715148898.65396171715244641.4409941715257241.7003561715271768.30176381715292152.86608841715330004.41626481715353713.42781571715353959.83065681715412668.46831631715421483.23257471715436334.75793931715520201.0295451715526648.21276971715527468.23268561715528972.9669821715529459.80643921715548182.89837461715602825.46457481715624287.64700171715666953.60590481715670258.04229781715681034.8107381715681373.08043051715862181.04882651715870345.8139851715870495.73219591715952418.20962721715953957.14005851716016439.23131821716026356.82077621716029493.3221591716031083.0943561716044060.71082471716107419.57978841716126517.3683791716131168.69529941716148891.67200921716149216.5821041716210413.7965631716312201.71627861716373672.36785031716374729.35419821716457578.06868461716467093.383061716559791.08338621716561161.53435441716649359.7539071716651785.40524051716723261.63200521716725596.59526781716732292.42133981716734447.8044291716738254.8956911716746654.24368071716795806.77896641716812563.0741851716892685.13354331716902147.31798151716903552.33264231716923921.77522521717066955.01724891717068917.04717661717072154.64399171717251267.23197651717259797.31061671717262953.80781751717328859.87784651717676565.94108441717861914.30391071717863020.84930681717927139.78493431717938355.69149681717953323.82942721717999765.11817811718009339.5952451718009454.02913121718009667.4100361718013654.53190851718016460.01057121718018761.15332411718020799.01913881718021245.15856621718025465.146841718026322.14862821718029950.58980631718041093.53587461718088975.1600171718098525.37702471718098991.82041171718099452.66476921718111343.16626361718114741.25173521718129965.94656441718167927.92333411718168560.61959651718170862.25188761718205019.47537661718206374.16787241718206647.1795651718208141.49481821718210905.61703281718270394.38123511718278706.33032561718287986.1937131718297994.59491591718336969.9835191718365449.34239961718449087.83051371718454283.21870951718456413.19333861718460153.46241951718462494.17207481718465987.28904911718467416.27678541718470343.79496341718477682.9318441718482373.43667821718515832.7972051718517249.02119351718517857.79042481718519972.8539831718522868.36958581718531550.47946141718536268.03831891718542101.57696131718544464.276851718619123.1634091718623185.88458681718636520.18447331718638800.48453331718731139.4622661718744170.95703461718774106.69617961718886170.088351718961712.35531521718968868.04600861718979695.67104221719060406.1220171719062040.21757941719067330.25522921719068089.06455061719076451.03764821719145795.36178421719151988.68255621719155248.8882151719162133.02871321719171629.7718651719242754.68141651719246705.8919081719255647.18871621719257347.07321881719298633.56316071719407710.83869461719491033.8175251719659127.47902351719661686.4932391719662640.99923061719664604.3216051719673418.46054081719677856.88689371719678098.51585631719678853.39937191719691556.0107241719694248.85178281719738870.07826381719739924.29021171719741111.60789011719742304.8520551719742716.78034661719745397.84074521719754662.89840941719760266.12941981719794972.6005541719825084.29679921719830253.9239311719836759.33914421719841637.71088621719842717.60566931719845321.64250181719847663.70107821719857525.72813531719993166.31000541720004409.5729961720018730.98016761720020182.87782071720076639.35904671720096106.61090231720113532.36414341720179036.01004391720265126.1817611720268654.5868861720282147.87318421720283309.32325241720286050.92650751720293539.3648961720348073.98572061720355917.47972461720362591.71961671720364407.29622911720429987.46009041720437485.89313361720441618.70600441720508195.45873951720518734.8392421720723289.42841981720871967.87330561720969642.51132971721145249.62304261721305348.6251181721379346.542811721406926.7735731721488540.2356821721496747.87938481721565527.91214751721574362.68826171721578502.43117141721580213.3311231721585283.3753051721628125.85017541721636883.68095471721651068.3836311721674353.60487581721711682.92611581721718456.25190661721736585.12386851721910443.05865841721911097.9222981721987871.73615431721989464.20908121722005684.10386231722009183.98562811722011469.2203711722014888.58855771722021975.44721461722083657.7424821722085815.53132181722096167.44949651722100696.7462071722149157.52232481722155656.36078931722163295.76613711722174676.3690631722242732.55940461722246601.0920391722252901.8107611722256046.73971531722258487.4373321722258901.9600681722263870.85462641722266409.4265291722267746.61000281722269621.92874881722269976.8815461722272080.77377251722279683.22267081722285241.02753781722286729.75908951722287985.7799481722299867.8714451722318171.4614381722346936.88357971722348798.46942781722350457.81067321722353627.2568861722357499.26558111722367575.99968431722373491.33078071722507532.24708371722515108.97734071722591849.9296011722703647.97711471722774371.71582841722860722.0833721722957642.21708731722965889.98333571722972359.45396161722984867.60560561723119754.11207841723125286.55064421723130127.51485061723134319.18638941723136059.16600351723137066.5406291723193843.56864331723198696.47698711723294038.37574581723295845.44823861723297533.78702881723303807.6631671723307181.10538461723311677.03078251723422079.64531681723457339.1525981723501078.41981941723503405.5784231723617569.60056951723639369.8436771723724588.10065871723789608.36872891723969341.08708981724070485.40928551724143436.30561071724158744.75811391724202777.0643011724301420.52415971724320167.54208281724326928.27127341724329651.45827651724339689.16775081724339990.81605431724341541.8335571724361752.17471031724675459.66274451724678562.51491741724679041.8596421724680019.75805571724740481.8159631724764160.67093681724772210.33077071724822514.46581531724931894.77922081725133285.29799841725140832.77638151725178025.79151321725179150.94023371725200755.48870351725202807.74458771725207502.73175141725208627.66635321725209216.05556461725210265.44690441725252365.3833031725281675.10662651725300399.91392231725540836.6651921725631556.60361741725822627.10982061725872571.50008231725884561.59261251726144055.4084121726302918.2109221726675560.78871441726731619.00652861726733403.45392541726734397.35323241726735635.69507741726747782.26425621726829193.35509751726830291.6796181726838130.2701831726852953.32955671726858668.94598631726904919.53113151726908011.78215241726911494.43632151726923822.73583151726924631.13999751726926654.4907061727094218.42981771727252570.93366581727281245.10181121727355214.64388871727355826.6178961727359034.26466751727360644.51546881727364225.8715341727365398.40147381727699176.51489191727760655.17109581727951236.031521727954405.64962171727957757.77329021727958178.89527631727959519.3105711728033650.33202581728045029.38966541728059516.23578881728060897.03357651728122955.8606541728129694.6456711728133522.16625431728139325.90391971728145836.68000821728194852.80935961728234083.04004381728241507.9161731728303752.22948271728337214.14192871728537254.20157051728732990.48960261728737796.45881251728739716.13933061728743550.084261728744005.3918461728745195.51385121728746301.37412671728747687.5570631728833762.35883451728835446.2922161728836591.77962781728837687.72793221728920301.63146951729092802.6129941729093469.09824441729093986.6930831729094596.3920461729096367.12394571729104951.39206271729127668.9245751729234880.59355141729257906.23548461729262780.74853061729333006.94400931729334137.91921041729336212.40924571729338537.22319481729339287.76037341729340708.85076141729342959.6031771729345579.34861141729352068.85322051729352424.3033391729355813.55383041729358559.69434331729367128.97711661729408008.7562531729410455.93828371729412778.66819211729447330.7101781729506929.79903321729550383.50321531729562047.72278021729772674.30436231729774243.54481581729788974.2966791729830363.88572481729956671.11215191729963276.13354231729964801.2759481730041059.24922511730042594.4898211730044967.31507661730052437.95801071730108706.1819951730118182.17060021730180022.8704031730203262.34906771730221702.35324031730275347.68835761730284724.74087071730285556.1908141730301942.04073381730374645.96319461730380770.90588331730404050.21319961730409146.01821851730413873.39013431730425842.61837341730477372.56358981730479560.97667481730551759.14125781730568814.75447271730572438.19093441730573549.2564731730579225.9238521730595578.01302431730646326.27951721730647944.81843971730737022.00499321730747490.06824851730807292.04786471730813368.64133481730818826.50661751730824558.75576351730832422.99776941730899305.0615351730901750.78711341730903102.00121621730971789.14266371730975168.8730961730982023.72336751731056436.06550221731059006.3753541731071324.57351161731148182.06626031731148462.44941141731155029.29867031731156907.49877831731167668.76448461731169795.64211731731171081.69893461731174489.80106231731229459.46800331731229698.89608241731233254.31718731731250434.28619031731481335.12306331731513305.40980241731593266.2619741731829257.91134291731859678.92372371731862005.49140671731922937.4808991731932247.01066061731932525.03579831731933290.09443261731935460.2790451731947768.1370441731963060.6405581731965814.97759751731997859.09550831732005512.74292661732031545.79197171732033235.34174281732036071.30061321732037983.13547731732041409.30651121732045107.55121021732263516.1040951732278310.46816371732288821.0565531732293225.38360171732383821.50968841732384069.83460351732391560.43771732433721.32781671732438713.17433931732441780.7008471732444579.79170161732451683.7766181732452619.78835271732457653.61890271732461172.61851021732467163.96287751732468839.23634151732469965.24506521732470239.99742651732470501.72090651732471055.29854061732520087.42624571732530123.6256731732536785.36732151732544673.93568091732553939.84375951732555010.63737251732562360.8003981732577912.6871631732579381.4846941732592567.86124521732594026.41688681732600123.13871861732605068.88938931732616986.9114541732619159.52321151732650631.55471561732720047.2405881732723299.8870821732728587.26730161732871729.11913281732948772.60584121732962637.1605561732975163.11275771732976290.6137441732985336.40084581732995963.96110731733080300.40849661733140107.68333481733155022.88794231733159221.4871291733168664.37563941733170027.81566981733170526.38246061733175309.14986661733219295.66059971733219681.74375251733224273.44269561733227643.3910411733228907.1991411733229826.99463961733234914.88147951733238777.20137861733242353.3587111733251189.9278881733255484.1180661733271589.04232071733293075.55299761733306828.96452671733309484.4286141733314197.22540021733315408.63991121733322593.26261733322805.56145381733333231.66890931733338012.36725621733557577.02903531733561313.32804731733565446.2815431733567333.90873651733567523.57054021733571119.16926811733573990.21949861733585274.73568651733585807.70079871733588017.7802691733593130.24049071733596018.95720121733609188.49137931733643746.43857721733650829.55517651733653518.41186571733656796.4539251733658330.072241733672789.5846831733673099.07036161733677665.48938061733732967.44802711733737559.55780841733739774.8239391733743548.28622531733743862.25829121733746858.26144361733748646.72557661733750237.3521711733761303.18399291733765178.02769851733822550.6699731733823340.01468631733826457.3003791733827822.37315151733833036.50665521733834839.1826851733836114.1890831733836604.02174851733840883.20230221733909333.22253161733909960.60128761734006546.8225221734015859.57260821734027149.3870951734036509.35217021734088813.24160461734092473.45144581734093224.58835391734159531.09753781734172373.82559251734177203.28432581734180637.15363741734189493.22910791734199074.094851734204520.1181031734215792.56901571734244208.42764541734262072.54748561734264107.63865041734268892.43243811734269365.42090751734271469.63599971734277423.22195431734290155.5247891734351728.73345951734367515.79722861734438331.95803671734439067.72983981734456547.34842541734461357.14716741734530139.5553771734588131.5415551734610976.74784561734693575.87978171734969824.56160281735013863.393161735215585.1146771735298797.99119881735300860.96658131735508440.68806081735560537.00754211735579463.11638711735594487.58908061735595948.66397571735597276.44437431735619132.0939121735711899.46031331735748282.272511735752879.14751721735771109.68907361735816480.08303861735818864.54984551735820574.48879741735845919.00464921735860298.96272641735905773.7076061735907315.48212431735920256.98129151735923066.94315771735927923.41648321735985947.44539171735987120.1806911735996630.83959561735997792.5823651735999950.93494461736005094.04602071736013959.72211721736091883.54373981736094621.82072661736109303.38124751736145589.5623011736158598.80606061736166007.97108551736240721.18058561736253866.97930461736259561.10710951736260639.09564881736326720.27908971736328441.73657161736441715.22370151736441948.95128971736448183.2816631736457756.60786081736667671.61953041736859448.04466371737053105.39502241737059294.32388951737218204.23131737230569.76234361737281191.78747031737308641.89546281737634796.05093771737661678.30621581737980414.56857161738176427.33152221738307157.1679331738509361.618441738511025.38118171738514914.97471881738516331.62643051738521441.32319571738525752.06775711738563699.85149531738565426.26452471738585137.30715081738597319.09383541738805958.55573341738865614.27569961739190092.90278551739725914.1677241739794922.60280971739988471.1611621740054329.53807951740079331.96067121740157595.89306021740220123.13252571740245134.83469081740306870.50918631740399755.20469451740424096.56160071740482149.7709031740504617.92714481740662913.58478671740698083.95707631740719951.12571741740758916.84956621740770227.28777481740838599.90834781740841180.05470851740846806.8733711740851730.32116771740864068.8188891740870144.50498751740909633.67035841740943265.17093921741538044.2799881741540280.86075281741615485.17051961742736965.52304531742812809.59154631742817938.266741742820838.3423121742833639.73128151742836382.87002781742890878.3034031742903231.48092751743006526.32749031743348943.7035481743704527.33931921744540122.66594081744542397.6184541744552562.3538921744553711.73710041745173335.05232761745238610.73597071745843195.26599981746226701.0918641746362227.3089311746371442.02811121746372752.96396041746447891.44518851746971136.59414241746972157.62861821746974457.8493371746976168.04008251747052875.46152851747480982.72086171747494506.47235631747495596.47780681747496096.58660771747501563.0468381747504104.17075041747506325.9508071747560842.93142221747572746.32942341747574020.4336941747574378.1243011747575177.46076971747579555.74680231747582533.39935111747582736.4808891747584502.74418571747590890.88166261747663855.65062121747762052.21985131748067768.55359531748070430.55718111748074382.30197071748084587.6802791748100243.06219581748262369.5918211748456997.30241161748502143.56055741748551733.06875921748559805.85630181748687418.24339271748692941.51643781748697135.5269361748702566.18927071748704892.67874261748707300.78871061748707718.06951361748710902.92918851748712630.29231881748772575.60379981748780746.9731851748787418.26495341748872035.61121321748878691.137971748896375.92971748900642.73245171749046627.53392841749098755.83221241749098959.20923261749099168.61557631749101223.54241181749119609.5599181749126667.21709511749136965.48203021749139791.37379071749205793.16769031749207480.8730421749207705.36759331749218861.07364541749271912.958471749280080.92087481749295870.75518011749309413.27836321749310948.2479821749322719.81444221749373678.24797731749375255.88597581749375475.07102351749390282.05390721749392292.0063081749411650.42451621749413965.12196371749475224.39129951749618675.85485481749622671.67921351749624056.94271451749627604.1784551749631181.01720761749632928.388051749633248.42225221749634804.01072031749635921.47261521749640795.06175831749655274.54887771749662043.67698741749712691.98407031749721876.21657251749732184.4471661749736626.7742331749739584.64724351749740402.61703251749747088.33462241749748466.53899031749750838.43557451749752305.12964371749783682.446221749811531.87015961749812424.43984911749815220.3855131749859800.50181271749861810.68900941749902117.18541221749904617.60818031749912253.1481761749913909.38116311750076587.25237131750112065.51739981750112549.35909461750113293.49248391750147068.9693321750147951.59855251750200400.22014521750319173.37273341750320656.22340271750335721.70233581750503005.99435231750505702.15230181750505889.32328081750516364.62822911750516682.09823581750520735.09064871750591072.01674371750619801.56257151750620371.7246161750622133.09173231750681332.28547381750940677.62030151751110771.93014931751115024.4489921751116291.45540211751189516.1089631751191203.62136581751197267.61229181751210591.699061751210808.46503661751286324.2863091751355187.47904781751545628.6297721751725864.76436571751730131.79488541751732922.95610931751740004.53788421751802693.42043191751853656.44941881751888514.45562741751977113.73002241751978375.45727251751980210.80578421751981578.71516081752053384.70437621752065147.01648551752066782.68813631752068878.81543951752205705.86502031752220216.62114951752246320.06772021752249909.7087711752317403.78078061752319959.82731491752406318.92591481752407259.95407271752421544.34403921752422710.55015231752425032.73874641752426826.2733981752428572.17700621752433706.0658221752470562.98645881752483585.27684041752484817.75912171752487219.72185131752581332.79816531752653249.8534491752655387.0071231752658130.9101921752659385.04600621752662426.3619591752668621.53872781752695270.23094871752755556.76991751752815643.08703021752824222.17550471752909383.60699961752912449.2338241752931172.30991841752932046.08516341752938425.21734791752979538.95104621753081962.70720271753090756.31310061753109911.16209861753527824.8208531753528157.58777211753528832.78555541753543391.409981753548006.04766771753555118.34784911753557058.28183871753607448.8085821753619533.97913721753621675.42673831753624357.04167771753628490.57589821753633928.4630891753634247.65696551753635835.1478181753637985.3761331753642657.74337051753705646.54954431753964966.3723731754036963.81071071754050075.4858231754051763.00968531754147508.76656821754147960.37546681754154766.89045071754161739.48721551754163737.6889791754210964.67577391754219537.72440741754222113.16079431754223091.64906881754223664.96145081754228602.35027861754229672.55927561754232636.3346941754233129.24810151754239954.64880471754241517.74627611754293618.73869231754310329.99401831754317864.02745131754318821.54698561754323102.69770261754326266.59494351754330431.04373651754334383.8229841754335714.09769081754394275.90666251754569461.6958781754638842.06614331754657332.2965881754661051.36486671754665334.8849631754718055.42017081754722367.38050371754836525.26578741754838348.94885041754838865.27615121754915063.0405931754922379.19625621754923244.57161741754929550.85405331754934157.59779951754989457.02608081754990760.36931751754998789.73707031755003472.47263961755091334.14983991755092562.45052361755103874.80169751755155650.49192211755157146.6223681755161682.15712331755166388.19822221755173045.7185681755174334.2213181755185779.42064291755186716.5619511755189286.1331981755242426.36476161755519872.06463531755528180.97155121755528528.62853481755528832.34833381755529449.05892421755529841.94665981755530424.19558621755531801.02439361755542591.2031921755546709.01237341755581286.38693331755683325.90864251755697406.07089071755767369.2794331755771352.36944061755779093.85620981755781792.09225491755786039.54400421755858394.51499061755864857.68235521755871908.5540961755872239.40110661755944972.05689141755963250.81905911755963438.96490861755965198.06602641755966671.70875931755967661.83248521756034035.27029371756051795.8273511756053720.38031081756062188.62394291756063534.1845211756068629.49149271756072172.11601281756125268.80325321756151453.8187271756310124.8685731756324844.69694781756482129.77022931756490613.15560961756492041.12433431756492297.4743671756513623.957081756514647.05277421756543727.9926171756545188.08750371756554689.8216321756560330.4979361756563740.7113121756565274.90660831756568027.52632161756623368.20361261756651846.51766971756657428.71791361756663741.77574421756668491.29928161756688997.64640711756705263.30104331756730683.43084431756812503.3911331756816382.50912021756880677.25349831757250586.60078881757252044.00713371757254258.84415481757315748.36797551757406692.55116631757427558.33150171757522892.84468961757593511.33569531757676782.52932741757759889.01814961757767620.0571711757769226.14481571757860829.75224731757861011.95556551757869302.40287541757870842.21012851757936618.8545211758094931.5402841758198530.53288751758272178.07883481758376917.19157841758379331.32556821758383837.43758921758384955.91952871758386059.87447021758387594.98469191758436846.8173221758444026.71285961758465789.753581758469660.50086121758470168.84960561758473722.39771131758789360.21657351758790715.03019021758803464.58468131758988044.04686881758991604.67435341759149102.85564831759492772.7183581759678936.99280551759680244.41957191759682618.7215971759997215.5191141760065958.82141760108993.57618381760110235.74441121760113550.87181661760177011.020731760181782.93854881760187005.60134651760192106.0860061760197207.4219841760199258.14967731760201985.65009261760203562.60572621760208440.80056051760260714.59390331760269934.64895941760285343.12197661760302129.65267131760328991.23364641760347755.98690061760350649.9220261760358687.67830591760362798.8370321760370432.53595111760424926.0255061760743184.63201121760744311.27082821760786622.23636051760788165.03988481760793302.1477371760793581.00444651760860182.22760991760863110.1014251760869362.4851031760869631.20522211760938861.72963521760972576.6875791761060407.88111571761060627.86563541761144889.48445651761148094.4665371761149201.68041321761219314.77552221761222483.27736571761295138.05956271761300300.05976561761311514.2513831761383799.72652271761391837.57163881761470800.4115141761501864.5615621761505443.42185241761568627.8543231761574494.27752451761580013.00882581761732663.23955371761733540.29735681761734029.47098021761736371.18000411761739191.4154661761739705.32874251761753667.99567171761756863.44928861761784016.66543271761815295.3384011761818717.73632571761828134.65532541761903405.21529581761907058.3059471761907853.07356211761916217.91197681761918750.98722891761919810.46501971761924888.20557641761931309.01599481761932455.5341991761943258.13832351761943965.9173671761998689.14334371762002422.82314631762003826.12135481762004604.3158771762010514.22436361762011210.89124921762016597.03093961762018766.23459271762020096.98681351762101868.87471441762105814.20747041762117386.51707461762172536.0202071762175528.28611851762182329.89773131762184577.847421762200953.02406841762253192.46915271762287934.7201151762422643.67606431762522533.03694341762528028.09290721762604673.09312731762616332.89323471762622168.34792021762622653.81842371762623239.4300881762685869.81218481762686662.3993391762687533.77702381762690043.77134161762690640.88656691762695418.03792051762709145.42883351763297104.580981763299241.28969961763302424.11725041763302843.86228871763303656.57493881763308095.12544541763314434.7122511763369939.32778621763382952.35389781763386880.2573951763389202.88072281763392117.76956531763546287.4585961763642087.21390341763659970.05781651763789967.2350981763795214.27324411763919897.74203251763924530.93485471763952917.04675961763987168.7900181764011135.03248621764218317.51825621764340352.97474771764360919.5237561764363105.4042141764526965.08457641765187128.96606761765355457.20101881765360544.06178261765361150.35600881765365518.7660051765557551.37651371765634926.0382451765640618.16870021765643253.3146741765643519.69737031765644942.7686081765650850.12580161765723889.33895751765725272.58981011765801621.52776551765879692.79019981765881108.2923851765890266.88562971765904510.36874341766061002.58671021766125878.0924161766175231.09851151766925374.73368381766996893.3731451767005790.16068861767008228.98308441767008524.3519591767008722.277691767009786.6732971767010541.95609551767013276.2328151767014306.68311551767015117.66693161767016373.33748561767086094.86997441767091943.21654251767092201.60667631767092814.322511767093453.33107881767270242.21536641767408827.13386231767450501.75768571767523607.15288781767524436.25480221767526671.70246891767540425.50893971767603172.05479241767608491.66707541767609798.80080491767780009.40121251767781869.36996481767783204.39632751767790049.159871767794832.20550161767797154.26203081767804637.35404421767805344.88099361767806485.79580351767862570.84585951767875104.49013021767876387.1385631767878636.14207961767880873.36738281767886064.7900161767887927.80501461767888628.77220651767894802.7501641767896425.17220471767954580.81757711767965181.28974031767970332.55244421767976705.94087121767978150.31396751767979970.38509061767982341.54357241768045908.30165961768048075.19306331768053087.31861191768053335.17539641768053645.28298431768057005.33032661768066054.97335241768079709.17248341768086210.00448131768134738.7489611768294958.7072611768308509.28162381768315525.73615461768317971.54583171768324985.50381061768384450.31180241768384903.74312451768388680.90803861768392012.94858881768393585.3805781768393995.64151621768397007.99611141768406785.83768421768407489.64632871768409265.181261768551967.76439951768562217.99268051768610315.5459591768648558.153921768750832.0425951768752477.22225881768754282.39400241768796055.877771769188973.98886591769356219.91804651769431235.54304531769520922.91533951769599853.44837931769601389.59619861769602998.44604521769608654.73905181769610587.53120471769613698.73730281769726072.5167361769754197.50043941769755012.88609891769788320.73522931769858771.11245351769880002.6400221769942094.34304521769950759.62865611770017332.54535651770029686.73525791770030911.36921741770035196.27489521770078295.91910531770155819.04716871770156062.72328571770198607.2284711770216427.27850631770217725.82147841770285886.35344841770290884.90398961770293022.25364641770293820.08989361770294246.49858431770296115.1938441770299476.89053541770304820.12695341770352845.59949111770360288.23392491770367647.6183741770375651.93329671770377722.19474721770388368.43299151770448360.88149361770474728.24455641770481662.81833741770482589.88003921770488483.83722141770547899.68135141770552992.3148081770630929.81703331770633593.05083631770639855.45341871770641556.83762381770666283.9656191770678866.937431770713538.44122551770808102.5597981770808949.6446791770809499.2195741770810416.91006471770899285.98089671771076383.70956751771153651.76371071771164919.83956381771165092.99137471771174054.22143321771175340.04150221771177045.09119531771185402.94351391771244500.35640861771600069.33150391771684144.1958011771757051.82674771771764404.84740111771780335.22727061771837797.45328641771839342.36841251771972863.80090481772004107.47609931772039629.94084841772097117.20003531772109451.20020151772125675.95705031772125857.190021772183872.96083351772280443.39041772295620.44625071772297315.33010551772298006.16521671772298862.35013271772328483.23607921772383354.17270871772383859.67349171772453976.5166041772713474.08007761772764991.76435041772787200.42355971772810020.21219421772905521.24598431772967859.26760581772984277.1005431772986433.85609721773059860.61029891773145094.80025391773145911.42583251773209770.56137851773327542.94483571773342123.46900181773389597.40498381773414356.9681911773416039.479741773416217.71348381773419126.79226261773433373.38669231773436829.7128131773496559.35769411773508591.08885051773526120.85893461773531469.85906171773532861.86214071773533352.6592681773664068.5733641773923117.08077051774116655.5106381774122638.22514531774123641.88898591774125088.17211991774165485.80263611774173634.33903151774178999.34086061774183816.01904231774191744.71987271774268550.01723621774527788.46656441774873687.7349881774875923.54350611774876751.77354171774880838.67538051774881356.113411775230959.73582771775232675.9200561775235024.41129371775242021.88784241775312892.665391775318498.7480911775319347.16049271775322263.85051471775381212.6245531775402348.91712781775462820.18094781775464128.60385511775478288.9307221775492883.68803621775494355.61733411775551100.70342451775737468.23703461776083199.4409181776342248.38125251776343741.35873751776344656.84962031776344823.2718941776494663.58264471776500579.0558131776513568.45815661776515798.23732261776521467.21749231776525755.44738361776530770.69265341776586552.67150241776602163.0317081776602999.49911571776688068.9822271776732694.04593831777121040.04677321777124071.1219561777126020.42327551777134818.39440461777287314.63329941777293598.26220231777363083.66518071777893423.46401861777895088.46678451777895860.43515851777897093.3858841777906171.800171777971134.0487721778058288.40560981778240440.64545181778329365.76004721778330451.60289481778332821.17423941778334531.54666111778342595.05410931778399875.18376181778419689.60360841778424127.0708861778487982.02455741778490235.47887951778512722.16216681778513868.5482841778514150.02312251778579208.82636931778579750.70454621778592818.33435651778593837.24621341778690465.584721778695987.13411741778697526.6658811778761332.9720331778822349.00370981778843702.19216871778918473.19561221778921342.1787031778931726.05583721778934249.29012421778934437.7146981778937818.14839361778942880.65417721778943688.6406221778945937.1907251778948525.945271779010660.48089271779012402.8849981779013545.70784571779014082.44581171779018379.58577371779019598.37050581779031500.34276341779032724.80927351779036530.4997151779039779.62068941779093071.12585621779097835.65313321779098505.47838691779100146.64374641779105919.20712781779107140.5768891779176813.17461751779177591.00395081779179103.9485821779179883.46228861779185903.12827781779188010.30328131779188332.78576521779199711.64825681779291274.87059261779375116.30314351779711775.9329841779718782.88222651779719462.58929511779720087.20665341779729556.75550171779729838.27185651779809157.15284131779811618.10328821779819147.38901331779821301.30405041779866487.12891531779872294.22598481779971079.62741731780155829.02630381780156437.50365951780156947.1906751780160264.74311021780167393.25985981780170098.30806231780172747.63186741780387294.64188241780398187.88314941780404797.27766011780815769.00067281780829125.25964361780848886.74698451780921520.99491741781093734.38310651781096055.84976481781098042.90676521781099588.2129331781102762.92132381781180914.85429571781261527.5583841781262166.32642581781262455.47228241781266268.58414151781354356.52117321781354995.9694651781355856.93816971781536853.31092361781703806.92632481781709239.78021071781709649.70756981781712321.38379761781718337.83594421781766440.45514631781770420.25207661781771329.15113041782058868.15240241782060757.39437151782114840.01730421782116626.14168121782118278.46144271782206800.38508151782208690.2186571782214986.56640481782215911.93149111782216753.3375161782217861.1438531782220507.59964751782221119.53614691782387963.94272471782391037.86762831782397174.43466951782400827.49992321782403418.57682781782407552.49232911782471685.10908841782486056.42131281782491119.7754541782492484.88775631782494767.62891581782495119.03816651782496927.16670061782502951.5276581782545134.69273971782631015.85844421782637542.97413681782647782.39912581782655816.30765841782665041.4627811782665991.96139241782667360.25157431782667581.47708061782737511.11845541782741219.0173351782808797.46143821782821919.54439121782822150.20869351782822770.9247681782827640.9542741782995600.16514921783076003.8864451783168083.37299471783169337.93949561783170232.14352231783171152.32074671783171554.32837651783174151.23807241783175503.07197071783176066.03923421783177692.68739181783179012.4248781783180240.505071783181436.92591291783278283.35669681783292257.8646151783517394.68319441783519695.6277161783678055.17990521783690220.13936731783712582.08824041783728419.41365361783729135.00310421783759453.8615671783761470.83648281783762862.82867961783766534.35036041783789595.08747321783930190.16791941783945570.6136721783954524.23125741783961828.6792711784028298.10868841784032600.80211161784036466.34077051784275841.48916361784366399.8074531784372627.88642331784374143.74483511784381186.08228351784389911.60351871784391089.69298031784392820.7430641784441094.15184241784454226.16887471784463132.38275381784464955.09228731784465761.79993341784466473.52550131784534975.79487631784608840.64008361784627943.05730491784637204.21883181784657189.48320531784657361.00413231784705158.30658131784715027.92925261784717991.8883981784733191.58883381784800377.45267271784812026.23560981784813186.95499831784814275.7592081784814470.29561351784818774.22292831784885821.62646681784901088.03214721784911607.10147881784916194.16596481784972617.54671784972803.68592141784973536.44179941784984817.86716681784986067.89907431784991877.94465471784998142.43659141785077031.5503931785084617.6083441785085343.4737631785086642.81846361785089769.95803481785137621.71359851785148601.48444631785172866.56524541785183014.3988751785218740.09921071785226243.70275641785228013.18298631785231361.67605071785240404.4484591785351675.21743441785496949.62526921785497755.40492131785677473.9457911785682237.71711851785766885.1947461785767243.61589121785772605.15616921785780183.1826661785782828.58324171785844265.65100531786268630.51386521786268947.91257071786269779.52634531786270697.67045071786277480.71831921786277724.14191751786281462.37932561786283154.36108371786283465.1903721786287166.76432871786289748.3343981786291875.15268561786293725.95022321786348241.80029181786352220.4185581786361747.21840071786366233.6671131786371555.18662381786372824.49700121786373802.18644671786377861.78411321786396710.64104411786403578.61991981786404487.37806181786404734.32843161786405449.91876441786436596.65412431786447073.79378181786447522.7193891786448405.54787921786449471.29032681786451444.1795711786452347.886241786452593.9396731786452926.5358991786456312.5733451786460743.97798971786463552.7407611786467845.41169861786474469.07857231786500206.03659271786562450.2208571786624610.81183391786686613.90171031786707650.41359851786728713.556651786729513.55272531786732847.73948051786775661.46056441786793299.49886561786793752.87393641786795187.76700571786795492.19988731786796902.2267191786864030.39654251786877454.05324031786878224.85780861786878707.51193381786880196.6659971786889576.6266361786896123.18303631786897808.01330881786959914.86220031786969834.2895571787034435.40246821787037132.78288671787041876.14791921787043670.97637461787052232.21001531787053261.528911787054828.71881531787057097.76064941787057270.45106361787080328.38963961787098382.79672071787212927.31802031787213906.47958251787391536.60465361787405049.95616221787413076.39776441787414062.51431941787415564.08572081787416411.7572251787418017.1897991787561357.46756271787562310.27913551787563996.93383121787565091.77498411787574301.54038881787588201.00754211787593104.40193721787642026.60537821787673561.52608231787674329.7224761787674711.51707051787677464.49858241787678337.43698141787681688.66121481787683130.10403851787687695.57127761787689287.68309451787690616.81437441787701810.4492311787703668.7168161787707222.34974881787708366.0833051787833483.0882821788012363.8917741788014226.56514121788014444.46203181788014831.32849721788027556.80003211788028811.14085361788029847.54328011788032884.15895151788037518.85965231788040681.6379951788076734.7216161788077227.50776861788077813.40856151788080193.68758751788083119.7505771788083817.84018371788095059.20750331788095390.66399481788097229.3971761788097679.40907861788098003.1718191788098465.73136541788102309.51320241788109877.86712551788112950.73934821788122140.83618191788172558.95067521788349675.4929531788421037.50810361788426780.8682451788428176.25174671788430564.5544511788430743.87801271788433679.29403541788435111.78655531788438488.66362931788446926.9636041788515909.69741731788516081.98195931788522742.14201621788618246.47165971788635186.9250721788635558.33422451788635789.4294821788636367.91405961788694058.5883521788695187.35930281788695679.84430241788695861.56550481788696174.07321571788696486.99952081788699610.1654271788706175.4002641788708791.35910771788768529.16503261788768847.25175241788769158.75513321788769956.4852821788856851.3099661788857231.0244051788864108.7148771788864607.17643431788870457.76393961788933503.53945111788933884.78966551788935130.28528831788935364.07300381788943599.84631631788963766.71460411788964690.96040131788994629.24461321788995358.84281789049116.39686181789049665.61125971789053429.83603051789053748.55635711789055270.97012281789057828.95167571789060636.77079321789117123.03734421789125148.24968121789129178.42693951789130927.8506781789146595.95088151789147921.85589051789149987.17254041789202919.9433471789239509.03819871789240837.55427121789242243.33970521789246296.43297581789251133.36522251789283294.90694831789298899.86048081789300585.6070341789324702.78062441789340077.6306211789398706.11733251789407509.91688921789498660.45305851789510669.77112251789510839.46737381789511619.68825751789581295.81189421789601219.44713191789739567.78348521789885723.33021471789885933.53306651789898352.98658251789905004.61845331789927305.62970261789936369.12114671789973334.6382191789992073.46435621789992512.85091611790001913.51180621790003970.81159541790004711.87018661790009748.20150661790010980.563481790042541.33307551790043246.03312541790044011.7960481790045365.07886651790045776.40539721790055634.55904561790056248.98219161790060735.58417271790063202.01464941790081459.97241231790082937.56307961790083490.03347731790084744.11084651790090112.46751881790100602.38838821790251685.559071790285748.06976461790285923.0950961790287196.05213281790307718.7959311790313539.11857491790318416.5424811790338813.12476831790339906.89636541790340205.84576921790348934.0324271790354642.9886841790356778.34959131790359760.3494821790361779.11455941790365161.28851681790403764.38521151790404822.77841931790406935.5803951790436526.46638541790488814.36095431790490416.58845541790490592.155171790492616.01131271790498171.64805581790504053.35340331790521353.2800581790522126.07214361790525340.22642921790533765.12383681790535505.65537071790549531.27069191790549787.546231790550871.74745061790552442.3069821790554260.66256551790576724.53606081790580253.77084781790597319.93879531790609658.3253711790678387.66511151790679391.60144541790683493.4025851790684819.89906951790685026.3671431790693709.90361431790698391.01632021790742067.88606551790750059.58717511790755282.54491231790755984.97108721790757072.51720711790757699.36573981790758011.12142591790832918.38622211790833628.34380031790836570.1869771790853896.1376691790861717.48689251790864015.2485381790865871.4113421790930662.4278971790930938.6585841790934191.4625721790947820.23689941791006632.2132861791104185.35599611791130144.40498351791180023.70980861791190422.93512341791194809.0171461791196869.236171791197896.1639331791203499.43079451791279736.86039731791292896.39418631791365933.61197641791390679.28499911791439538.93790341791478541.71099541791619004.99550531791641930.47821661791646342.44199751791650750.58091661791651538.68789551791652404.38552381791652656.8551831791712241.5331911791714077.8119021791714719.1824621791715115.86821131791715818.93575261791717070.63279871791719290.0486511791739049.2688761791806819.58328531792320095.47749421792324660.4223321792331567.27418541792334734.33781481792336099.6263131792343269.26501541792347633.77702141792348030.62554361792388630.0850941792389169.57291321792395942.16618731792418086.23562261792438008.4442681792492198.00541161792497253.00689581792535378.33694981792569620.993891792674349.8321111 ro8o6kw5wqa7lxadtoxqioa44gmakmq Graham Court 0 113152 769782 763812 2026-10-22T19:32:03Z Testvinca31 47963 769782 wikitext text/x-wiki {{Multiple issues| {{Non-free|date=July 2020}} {{Cleanup reorganize|date=July 2020}} }} {{Copypaste|date=July 2020}} {{Use mdy dates|date=December 2019}} {{Infobox building | name = Graham Court | native_name = | former_names = | alternate_names = | image = Graham Court.jpg | alt = | caption = | map_type = | map_alt = | map_caption = | altitude = | building_type = | architectural_style = [[Italian Renaissance]]<ref>{{cite web|url=https://books.google.com/books?id=xvGhQoNT27IC&lpg=PA315&dq=%22graham%20court%22%20astor&lr=&pg=PA315#v=onepage&q=%22graham%20court%22%20astor&f=false|title=The New York Chronology: The Ultimate Compendium of Events, People, and Anecdotes from the Dutch to the Present. By James Trager. 2004.|publisher=|accessdate=September 17, 2014}}</ref> | structural_system = | cost = | ren_cost = | location = [[Harlem]], [[Manhattan]], [[New York City]] | address = 1921-1935<ref> [http://a810-bisweb.nyc.gov/bisweb/PropertyProfileOverviewServlet?boro=1&houseno=1921&street=Seventh+Avenue&requestid=0&s=A03C41B885B461E4F46BD08866A7430E NYC Department of Buildings "Property Profile Overview" using a "BIS (Building Information System) Web Query"] </ref>(or 1923-1937<ref name="Landmarks Preservation Commission"/>) 1925 [[Seventh Avenue (Manhattan)|Adam Clayton Powell Jr. Boulevard]], [[Manhattan|New York]], [[New York (state)|NY]] 10026 | client = | owner = | current_tenants = | landlord = | coordinates = {{coord|40|48|12.26|N|73|57|8.28|W|type:landmark_region:NY|display=inline,title}} | start_date = 1898<ref name="NYSUN"/> | completion_date = 1901<ref name="NYSUN"/> | inauguration_date = | renovation_date = | demolition_date = | destruction_date = | height = Eight stories<ref name="NYSUN"/> | diameter = | other_dimensions = | floor_count = | floor_area = | main_contractor = Developed by [[William Waldorf Astor]]<ref name="NYSUN"/> | architect = [[Clinton and Russell]]<ref name="Landmarks Preservation Commission"/> | architecture_firm = | structural_engineer = | services_engineer = | civil_engineer = | other_designers = | quantity_surveyor = | awards = | ren_architect = | ren_firm = | ren_str_engineer = | ren_serv_engineer = | ren_civ_engineer = | ren_oth_designers = | ren_qty_surveyor = | ren_awards = | url = | references = }} '''Graham Court''' is a historic apartment building in [[Harlem]], [[Manhattan]], [[New York City]], along [[Adam Clayton Powell Jr. Boulevard]] between West 116th and 117th Streets. It was commissioned by [[William Waldorf Astor]], designed by the architects [[Clinton and Russell]], and constructed in 1899-1901 as part of the great Harlem real-estate boom.<ref name="Landmarks Preservation Commission"/> The [[New York City Landmarks Preservation Commission]] designated the building a landmark in 1984, characterizing the Graham Court as "one of the premier reminders of the urban development of Harlem at the turn of the century" and "one of the signal achievements in the history of the apartment house in New York City."<ref name="Landmarks Preservation Commission">{{cite web|url=http://s-media.nyc.gov/agencies/lpc/lp/1254.pdf|title=Graham Court Apartments|date=October 16, 1984|website=|publisher=[[New York City Landmarks Preservation Commission]]|access-date=December 9, 2019|ref={{harvid|Landmarks Preservation Commission|1984}}}}</ref> ''[[The New York Times]]'' suggested that it might be Harlem's "equivalent to [[the Dakota]]".<ref name="dame"/> ==Description== Graham Court has 800 rooms,<ref>{{Cite news|url=https://www.nytimes.com/2009/05/31/realestate/31scapes.html|title=Buildings for a City He Could Live Without|last=Gray|first=Christopher|date=May 28, 2009|work=The New York Times|access-date=December 9, 2019|language=en-US|issn=0362-4331}}</ref> currently divided into 93 apartment units.<ref name="Renovation"/> The property is eight stories<ref name="dame">{{Cite news|url=https://www.nytimes.com/1987/07/12/realestate/streetscapes-graham-court-grande-dame-tries-regain-her-respectability-harlem.html|title=Streetscapes: Graham Court; Grande Dame Tries to Regain Her Respectability in Harlem|last=Gray|first=Christopher|date=1987-07-12|work=The New York Times|access-date=2019-12-09|language=en-US|issn=0362-4331}}</ref> and contains eight elevators.<ref name="welcometoharlem">[http://www.welcometoharlem.com/page/central_harlem_history/;jsessionid=d8e128o00cg?ct=cdisplay&nt=true&cd_v=dispclean&cd_p=-1&cd_eid=38068 "Central Harlem History" at welcometoharlem.com, 12/30/05] {{webarchive|url=https://web.archive.org/web/20110718023555/http://www.welcometoharlem.com/page/central_harlem_history/%3Bjsessionid%3Dd8e128o00cg?ct=cdisplay&nt=true&cd_v=dispclean&cd_p=-1&cd_eid=38068 |date=July 18, 2011 }}</ref> It runs the full length of the block between 116th and 117th Streets along Adam Clayton Powell Jr. Boulevard, with a depth of {{Convert|175|ft||abbr=}} on the side streets.<ref name="dame"/> ===Exterior=== It is a "boxy mass" designed in the mode of an Italian [[palazzo]].<ref name="dame"/> The first two floors of the exterior [[facade]] are of rusticated limestone, with tan or gray brick above and a crowning story of foliate [[terra cotta]] capped by a copper cornice.<ref name="dame"/> ==== Main facade ==== The building is divided horizontally into three parts. The main facade, on [[Seventh Avenue (Manhattan)|Adam Clayton Powell, Jr., Boulevard]], is divided into five parts vertically as well, having slightly projecting central and end pavilions. The two-story rusticated base, consisting of [[limestone]] set in alternating wide and narrow horizontal bands which show only the horizontal joints, has simple rectangular [[wikt:fenestration|fenestration]] and rises above an areaway with molded [[watertable]] and [[wrought-iron]] railing.<ref name="Landmarks Preservation Commission" /> Capping the base is a projecting [[stringcourse]] which is decorated with a wave molding on the center and end pavilions. The monumental main entrance, leading through an arcade to the interior courtyard, is a [[Palladian motif]] consisting of a central molded arch, with a keystone ornamented with a [[cartouche]], rising from an interrupted entablature which is supported by pinkish polished [[granite]] columns of composite order and [[pilaster]]s with [[entasis]]. A pair of large central ornamental wrought-iron gates is flanked by smaller gates. The [[spandrel]]s carry inset granite [[roundel]]s. The entrance is flanked by round-arched first-story windows with molded surrounds and keystones and second-story rectangular windows with surrounds.<ref name="Landmarks Preservation Commission"/> The inscription "Graham Court" appears above the arch, flanked by horizontal terra cotta panels with [[anthemion]] motif decoration. The arcade leading into the courtyard continues the treatment of columns and pilasters. A barrel vault, faced with [[Guastavino tile]]s, rises from the [[entablature]] and is decorated with broad ribs which extend from the columns.<ref name="Landmarks Preservation Commission"/> The pavilions of the midsection of the building, extending from the third through the seventh stories, are framed by [[Quoin (architecture)|quoin]]s; the rusticated stone bands of the central pavilion are punctuated by fenestration. All windows have simple rectangular terra cotta surrounds; those at the fourth, fifth, and seventh stories of the center most portion of the central pavilion have entablatures.<ref name="Landmarks Preservation Commission"/> Each floor is separated by a continuous stone stringcourse. Above the entrance on the third story, between the windows, are terra cotta panels of foliate design. The fourth floor of the central pavilion has a stone balcony with cartouches (part of the coping is missing), and there are also iron balconies with a harp motif at the fourth-story end and a seventh-story central and end pavilions.<ref name="Landmarks Preservation Commission"/> The seventh story is capped by an ornamental terra-cotta stringcourse (reeds bound by bay leaf garlands) with central and end cartouches. The top story has alternating round-arched windows and terra-cotta panels with decoration of classical derivation. The metal [[cornice]], originally denticulated and [[modillioned]], has been removed; remaining are the [[dentils]] and an [[egg-and-dart motif]] molding. A [[parapet]] wall, acting originally as subtle [[pediment]]s for the central and end pavilions, is now fully exposed and covered with [[tar]].<ref name="Landmarks Preservation Commission"/> ====Side facades==== The two side faces are identical mirror images (except for two round-arched entrances at either end on 116th Street and one larger one at the western side on 117th Street) and continue the same treatment as the main facade. The two side facades are arranged vertically as three pavilions. The unarticulated rear facade is of plain brick.<ref name="Landmarks Preservation Commission" /> ====Courtyard==== The [[courtyard]], reached by an open arcaded entry from Seventh Avenue, is 79 feet by 108 feet square and was originally planted with grass and ornamental shrubbery.<ref name="dame"/> The court layout was thoughtfully designed to comply with typical courtyard plans of the time. One of the great issues in apartment design at the turn of the century was the disposition of the courts - often reduced to mere air shafts. But because of its size, Graham Court could have a courtyard shared with no other building.<ref name="dame"/> In the courtyard, a driveway and sidewalk encircle an oval garden area with walks in a cross pattern which originally had a central fountain (the stone base remains).<ref name="Landmarks Preservation Commission"/> Eight iron lampposts were located in the oval and one pair flanked each of the four interior entrances (only four posts, one globe, and the stone pedestals remain). The reverse of the front facade entry arch, on the courtyard, is similar to it but without the keystone and is flanked by a pair of blind oval bulls-eyes with top and bottom keystones.<ref name="Landmarks Preservation Commission"/> The building is entered from the courtyard through four porticoes with columns of composite order, Guastavino tile ceilings, and balustrades (part of the one at the northeast corner is missing) which are set against the angled corner. Wood double doors with glass central panels and [[transom (architectural)|transoms]] are surrounded by egg-and-dart moldings and are flanked by small round-arched windows (most of which have been filled with polished granite). The courtyard walls maintain the building's overall horizontal division and materials, except that the base is one story high and is composed only of wide limestone bands and the brick is set in horizontal bands with plain and denticulated stringcourses.<ref name="Landmarks Preservation Commission"/> The first story has simple rectangular fenestration; the windows of the second through seventh stories have flat-arched lintels with triple keystones (some have end voussoirs), except for the second-story corner windows above the entrance porticoes which have molded surrounds with cartouche keystones. The top story has round-arched windows with keystones and is capped by a copper cornice with egg-and-dart and patterned motif moldings.<ref name="Landmarks Preservation Commission"/> ===Interior=== The planning of the apartments was a bit crude. Andrew Alpern, in his book ''Apartments for the Affluent,'' says the building has an "awkward circulation pattern" and the bedrooms tend to be small and narrow. But each apartment combines features - oak kitchen cabinets, mosaic foyer floors, mahogany and oak flooring, paneled dining rooms and multiple fireplaces - that later, simpler buildings could only sample.<ref name="dame"/> ==History== ===Origins=== The land on which Graham Court stands was acquired by [[William Backhouse Astor, Sr.|William Backhouse Astor]] in the 1860s and was transferred to [[William Waldorf Astor]] by the Astor estate in 1890. Graham Court was constructed by architects [[Clinton and Russell]] at an approximate cost of $500,000 as one of New York City's largest and finest "flathouses" (apartment buildings). The builder was John Downey.<ref name="Landmarks Preservation Commission"/> The Graham Court then got caught in the market collapse of 1904–05, which hit Harlem particularly hard. Moving up from the [[West Side, Chicago|West Side]], blacks turned Harlem into a "community where Negroes as a whole are better housed than in any other part of the country," according to historian Gilbert Osofsky.<ref name="NYSUN">{{Cite web|url=https://www.nysun.com/real-estate/once-heralded-address-lags-behind-rest-of-harlem/26140/|title=Once-Heralded Address Lags Behind Rest of Harlem|last=Vitullo-Martin|first=Julia|last2=|first2=|date=2006-01-19|website=The New York Sun|access-date=2019-12-09|archive-date=December 9, 2019|archive-url=https://web.archive.org/web/20191209141845/https://www.nysun.com/real-estate/once-heralded-address-lags-behind-rest-of-harlem/26140/}}</ref> The building remained under the control of the William Waldorf Astor estate until 1933.<ref>New York County, Office of the Register, Liber Deeds and Conveyances. Cited in {{harvnb|ps=.|Landmarks Preservation Commission|1984}}</ref> The building was one of the last major apartment buildings in Harlem to become integrated. One source says that it was not opened to black residents until 1928;<ref>Gilbert Osofsky, Harlem: The Making of a Ghetto (New York: Harper Torchbooks, 1966)</ref> another asserts that it did not rent to any black tenants until 1933, when new management's decision to "accept colored was accompanied by a reduction in services and an increase in the reduced, Depression-era rents."<ref name="NYSUN"/> Many eminent blacks moved in, including Dr. Cyril Dolly, a physician who organized the Consolidated Tenants League to protect tenants.<ref name="NYSUN"/> Famous residents also include James Pemberton and his wife Edna. James Pemberton was member of the state assembly representing Harlem, part of the [[Tammany Hall]] establishment and led protests at Yankee Stadium pressing for the integration of the game. On opening day 1945 after acquisition of team by MacPhail, Webb and Topping Pemberton led a group of protesters carrying signs that asked, "If we can pay, why can't we play?" and, "If we can stop bullets, why not balls?" ===Decline=== By the 1960s, the building had begun a precipitous decline.<ref name="Renovation"/> Then, Graham Court fell into city hands in 1978, when its owner failed to pay taxes.<ref name="NYSUN"/> In 1979, Mohammed Siddiqui, a pharmacist, bought the building for $55,000 and a promise to pay $150,000 in back taxes.<ref name="NYSUN"/> The sellers were Bankers Trust and the Astor Trust.<ref name="rescue">{{Cite news|url=https://www.nytimes.com/1987/04/04/nyregion/rise-in-values-spurs-rescue-of-buildings.html|title=Rise in Values Spurs Rescue of Buildings|last=Williams|first=Winston|date=1987-04-04|work=The New York Times|access-date=2019-12-09|language=en-US|issn=0362-4331}}</ref> But Siddiqui fell behind on his tax bill and, according to the tenants association, let the building slide further into disrepair. In the meantime, some residents said drugs were being sold illegally from apartments in the building.<ref name="NYSUN"/> During this six-year window of ownership by Siddiqui, tenants ran the building with the help of a court-appointed administrator.<ref name="rescue"/> By 1986, the city moved to foreclose the building from Mohammed Siddiqui for nonpayment of $933,000 in taxes.<ref name="NYSUN"/> It looked as though the city would foreclose on the building for delinquent taxes, allowing the tenants to buy their apartments for a mere $250 each under a city sale program.<ref name="rescue"/> But in mid-February, only hours before the foreclosure was to become final, the landlord took advantage of the city's four-month grace period and handed $933,000 to city tax collectors to reclaim the building. Then, Mr. Siddiqui, whose pharmacist license was suspended that year for three months for "negligence" in handling prescription drugs, sold it for $2 million to Leon Scharf, a West Side real estate investor with a large apartment building portfolio throughout Manhattan.<ref name="NYSUN"/> In 1986, Mr. Scharf told the New York Times that he was spending $1 million on improvements that year, and was optimistic about the future of the building: ''Eventually, maybe we would go to a co-op plan'' he said.<ref name="dame"/> In 1990, movie producer [[George Jackson (film director/producer)|George Jackson]] used Graham Court as the setting for a crack factory in ''[[New Jack City]]'', a depiction which the New York Magazine real estate section characterized as "all-too-believable".<ref name="NYMAG">{{cite web|url=http://nymag.com/nymetro/realestate/features/2652/index3.html|title=REAL E$TATE 2000: Uptown Boomtown|last=|first=|date=April 10, 2000|website=NYMag.com|access-date=December 9, 2019}}</ref> ===Revitalization=== In 1998, Mr. Scharf sold the majority interest to the current owners, the "Graham Court Owners' Corporation", under the management company "Residential Management",<ref name="Renovation">{{Cite news|url=https://www.nytimes.com/1994/04/03/nyregion/neighborhood-report-harlem-when-renovation-erases-the-past.html|title=NEIGHBORHOOD REPORT: HARLEM; When Renovation Erases the Past|last=Kennedy|first=Randy|date=1994-04-03|work=The New York Times|access-date=2019-12-09|language=en-US|issn=0362-4331}}</ref> who still owned the building as of 2003.<ref name="GCOC v. Green">{{cite web|url=http://www.nycourts.gov/reporter/3dseries/2006/2006_50333.htm|title=Graham Ct. Owners Corp. v Green|publisher=|accessdate=September 17, 2014}}</ref> The Graham is currently home to notable residents such as radio [[talk show]] host [[Alex Bennett (broadcaster)|Alex Bennett]], who fell in love with the apartment complex from the first time he and his girlfriend saw it. Major interior designer [[Sheila Bridges]]<ref>{{Cite news|url=https://www.nytimes.com/2013/07/18/garden/weeding-out-the-riffraff.html|title=Weeding Out the Riffraff|last=Green|first=Penelope|date=2013-07-17|work=The New York Times|access-date=2019-12-09|language=en-US|issn=0362-4331}}</ref> lives in the same unit in Graham Court where the director [[Spike Lee]] shot his 1991 film ''[[Jungle Fever]]''. Bridges, whose unit still contains the original built-in cabinetry and [[wainscoting]],<ref>{{cite web|url=http://www.newyorksocialdiary.com/NYSDhouse/sheilabridges.php|title=New York Social Diary - NYSD House|publisher=|accessdate=September 17, 2014}}</ref> had to clean up "the fake-blood stain left over from the scene where [[Samuel L. Jackson]] is shot at the end".<ref>{{cite web|url=http://www.brownalumnimagazine.com/content/view/1706/40/|title=Brown Alumni Magazine - Designing Women|publisher=|accessdate=September 17, 2014}}</ref> ==Tenant concerns== {{Update|type=section|date=November 2010}} ===Interior renovation=== In the early 1990s, the Graham Court Owners Corp. began a multi year renovation of the building's interior, which is not protected by the building's landmark code.<ref name="Renovation"/> A representative of Residential Management explained: "Basically, the rent stabilization law does not allow us to increase the rent unless we've put substantial money into renovating the apartments and that's what we're doing."<ref name="Renovation"/> The New York Times cited tenants who said that the purpose of the renovation was "to raise rents and eventually turn the building into a co-op."<ref name="Renovation"/> "What they do is just go in and strip the apartment – original mirrors and oak cabinets in the kitchen are taken out and they don't even save these things. It's all just trashed and the more valuable things, I suppose, are sold."<ref name="Renovation"/> ===Window replacement=== In 1996, the landlord received permission from the [[New York City Landmarks Preservation Commission]] to install new windows after an inspection found that 20 percent of them were beyond repair.<ref name="windows"/> The plan called for replacing the building's 400 original mahogany windows with aluminum ones.<ref name="windows"/> An employee of the landlord said the repairs were necessary, and said that the company planned to install the aluminum windows and seek rent increases.<ref name="windows"/> In the summer of 2000, in a survey by the tenants association, only two of 55 respondents wanted their windows replaced; most wanted them repainted and repaired. Some tenants were quoted as saying that was unnecessary, and was contrived to drive up the rent, which can be increased if certain work is done to the building.<ref name="windows"/> The tenants enlisted the support of Community Board 10, hoping that the Department of Housing and Community Renewal would reject the owner's request for a rent increase. But officials at the housing department said it was unlikely that the agency will intervene before the new windows are in place.<ref name="windows"/> ===Security services=== As early as 2000, the guardhouse was gone,<ref name="windows">{{Cite news|url=https://www.nytimes.com/2000/12/24/nyregion/neighborhood-report-harlem-tenants-suspect-a-plot-in-a-plan-to-replace-windows.html|title=NEIGHBORHOOD REPORT: HARLEM; Tenants Suspect a Plot In a Plan to Replace Windows|last=Day|first=Sherri|date=2000-12-24|work=The New York Times|access-date=2019-12-09|language=en-US|issn=0362-4331}}</ref> and as of 2006, the building had no doorman or intercom system.<ref name="NYSUN"/> While a security guard on duty from 4 p.m. to midnight would admit visitors, the rest of the time tenants had to go down to the gate to greet guests. Residents said there was a direct connection between the lack of security and the regular presence of drug dealers, some of whom live in the building.<ref name="NYSUN"/> In 2007, tenants sought a reduction in rents on the grounds that a reduction in building security constituted a reduction in building-wide services, and got a ruling in their favor from the DRA (Directory and Resource Administrator).<ref name="DHCR">{{cite web|url=http://findarticles.com/p/articles/mi_hb6166/is_2007_June/ai_n29356979/|title=Guard house replaced by security guard office and intercom|work=New York Landlord v. Tenant|via=FindArticles.com|publisher=Describing Graham Court Tenants Association: DHCR Adm. Rev. Docket No. UL430016RT|date=March 29, 2007|accessdate=September 17, 2014}} {{Dead link|date=September 2026 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> Landlord then signed a settlement agreement with tenants and filed an application to decrease or modify services. The DRA granted landlord's application, noting that landlord and tenants agreed that the security guard be located so that he could see and be seen at two spots within view of the front gate of the building. Landlord then filed a second rent restoration application, which the DRA granted and the DHCR affirmed; a DHCR inspector observed a security guard sitting at a security station designated as one of the two viewing spots in the agreement between landlord and tenants.<ref>{{cite web|url=http://www.thefreelibrary.com/Landlord+restored+security+guard+service.-a0215924746|title=Landlord restored security guard service. Graham Court Tenants' Assn.: DHCR Adm. Rev. Docket Nos. XB430036RT, XB430043RT (7/10/09) 3-pg. doc.|publisher=|accessdate=September 17, 2014|archive-date=October 17, 2012|archive-url=https://web.archive.org/web/20121017214317/http://www.thefreelibrary.com/Landlord+restored+security+guard+service.-a0215924746|url-status=dead}}</ref> ==References== {{reflist}} {{Harlem}} [[Category:Residential buildings completed in 1901]] [[Category:Apartment buildings in New York City]] [[Category:Residential buildings in Manhattan]] [[Category:Harlem]] [[Category:Seventh Avenue (Manhattan)]] [[Category:1901 establishments in New York (state)]] [[Category:New York City Designated Landmarks in Manhattan]] <noinclude> <small>This page was moved from [[:en:Graham Court]]. Its edit history can be viewed at [[Graham Court/edithistory]]</small></noinclude> lw1g0j2rf4k82x62lm807hp5pbzcglg Sheikh Rashid bin Saeed Crossing 0 113226 769812 733939 2026-10-22T21:32:24Z Testvinca31 47963 769812 wikitext text/x-wiki {{outdated|2019|date=November 2019}} {{Infobox bridge |bridge_name = Sheikh Rashid bin Saeed Crossing |image = |carries = Vehicles and [[Dubai Metro]]'s Green Line |crosses = [[Dubai Creek]] |locale = [[Dubai]], [[United Arab Emirates]] |maint = Roads and Transport Authority |designer = FXFOWLE Architects |design = [[Arch bridge|Arch]] |mainspan = {{convert|667|m|ft}} |length = {{convert|1600|m|ft}} |width = {{convert|64|m|ft}} |height = {{convert|190|m|ft}} |load = |clearance = |below = {{convert|15|m|ft}} |traffic = |begin = |complete = |cost = US$817 million |open = |coordinates = {{coord|25|12|40.88|N|55|20|42.38|E|display=inline,title}} }} '''Sheikh Rashid bin Saeed Crossing''', also known as '''Sixth Crossing''', was reported {{As of|2008|alt=in 2008}} as a future bridge in [[Dubai]], [[United Arab Emirates]].<ref name="GN">{{cite news |first=Ashfaq |last=Ahmed |title=Dh3b arch-bridge will be sixth Dubai Creek crossing |url=http://archive.gulfnews.com/articles/08/01/29/10185678.html |newspaper=[[Gulf News]] |date=2008-01-29 |accessdate=2008-02-24 |url-status=dead |archiveurl=https://web.archive.org/web/20080607035247/http://archive.gulfnews.com/articles/08/01/29/10185678.html |archivedate=2008-06-07 }}</ref><ref name="EB">{{cite news |title=Dh3bn sixth creek-crossing announced |url=http://www.business24-7.ae/cs/article_show_mainh1_story.aspx?HeadlineID=1598 |newspaper=Emirates Business 24/7 |date=2008-01-29 |accessdate=2008-02-24}}</ref><ref>{{Cite web |title=Dubai to build world's longest single arch bridge |url=http://www.ameinfo.com/150163.html |publisher=[[AMEInfo]] |date=2008-03-16 |accessdate=2008-05-01}}</ref> If completed, it will become the world's longest [[arch bridge]], with a main span {{convert |667|m|ft}} long. The bridge's overall length will be {{convert|1.6|km|mi}}.<ref name="GN"/><ref name="EB"/> The bridge will be {{convert|64|m|ft}} wide and will rise {{convert|15|m|ft}} above the water.<ref name="GN"/> The bridge, designed by FXFOWLE Architects,<ref>{{cite magazine |first=Matt |last=Sullivan |title=Dubai's Mile-Long Super Bridge Set for March Construction |url=http://www.popularmechanics.com/science/extreme_machines/4249163.html |magazine=Popular Mechanics |date=2008-02-12 |accessdate=2008-02-24 |url-status=dead |archiveurl=https://web.archive.org/web/20080229104954/http://www.popularmechanics.com/science/extreme_machines/4249163.html |archivedate=2008-02-29 }}</ref> with lighting by [[AWA Lighting Designers]],<ref name = "Model Behavior">Minutillo, Josephine. "Model Behavior: Anticipating Great Design." Architectural Record Dec. 2008: n. pag. Web.</ref> will cost [[United Arab Emirates dirham|AED]] 2.5 billion.<ref name="GN"/> It will be a part of a test123 AED 3 billion roads project near The Lagoons.<ref name="EB"/> The bridge is expected to be complete in 2015.{{update inline|date=March 2019}}<ref>[http://www.roadtraffic-technology.com/projects/sheikh-rashid-bin/ roadtraffic-technology.com: Sheikh Rashid bin Saeed Crossing, United Arab Emirates] {{Webarchive|url=https://web.archive.org/web/20200918234952/https://www.roadtraffic-technology.com/projects/sheikh-rashid-bin/ |date=2020-09-18 }}{{Unreliable source?|reason=domain on WP:BLACKLIST|date=June 2016}}</ref> The bridge will link the localities of [[Al Jaddaf]] and [[Bur Dubai]]. It will have six lanes of [[Transport|traffic]] in each direction and will be able to carry 20,000 vehicles per hour.<ref name="EB"/> In the center will be a track for [[Dubai Metro]]'s [[Green Line (CTA)|Green Line]].<ref name="GN"/> ==See also== *[[List of bridges and tunnels in Dubai]] *[[List of longest arch bridge spans]] ==References== {{Reflist}} ==External links== * [http://www.fxfowle.com/projects/35/sheikh-rashid-bin-saeed-crossing/ Bridge description at FXFOWLE Architects webpage] {{Bridges and tunnels in Dubai}} {{Dubai topics}} {{-}} [[Category:Bridges in Dubai]] [[Category:Proposed bridges in Asia]] [[Category:Through arch bridges]] {{UnitedArabEmirates-bridge-struct-stub}}<noinclude> <small>This page was moved from [[:en:Sheikh Rashid bin Saeed Crossing]]. Its edit history can be viewed at [[Sheikh Rashid bin Saeed Crossing/edithistory]]</small></noinclude> m3wxtdrnabr1mm3hi077dyu3w37nmis Theanine 0 113569 769813 737133 2026-10-22T21:34:15Z Testvinca31 47963 769813 wikitext text/x-wiki {{distinguish|text=''[[threonine]]'', a distinct [[amino acid]], or ''theine'', an archaic synonym of [[caffeine]]}} {{Infobox drug | image = L-Theanine.svg | caption = <small>L</small>-Theanine | alt = skeletal formula of L-theanine | IUPAC_name = (2''S'')-2-Ammonio-5-(ethylamino)-5-oxopentanoate<ref name = RSC_Chemspider/> or ''N''-Ethyl-<small>L</small>-glutamine | tradename = | Drugs.com = | pregnancy_US = A | legal_AU = | legal_CA = | legal_UK = | legal_US = OTC | legal_UN = Unscheduled | licence_US = | dependency_liability = None | addiction_liability = | routes_of_administration= [[Oral route|Oral]] <!--Pharmacokinetic data--> | bioavailability = | protein_bound = | metabolism = | onset = about 1 hour<ref name="PK">{{cite journal|last1=Scheid|first1=L.|last2=Ellinger|first2=S.|last3=Alteheld|first3=B.|last4=Herholz|first4=H.|last5=Ellinger|first5=J.|last6=Henn|first6=T.|last7=Helfrich|first7=H.-P.|last8=Stehle|first8=P.|title=Kinetics of L-Theanine Uptake and Metabolism in Healthy Participants Are Comparable after Ingestion of L-Theanine via Capsules and Green Tea|journal=Journal of Nutrition|volume=142|issue=12|year=2012|pages=2091–2096|issn=0022-3166|doi=10.3945/jn.112.166371|pmid=23096008|doi-access=free}}</ref> | elimination_half-life = Capsule ~1.2 hours <br /> Green Tea ~0.8 hours<ref name="PK"/> | excretion = <!-- identifiers --> | index_label = | index2_label = | CAS_number =3081-61-6 | CAS_number_Ref = {{cascite|correct|??}} | ATC_prefix = none | PubChem = 439378 | ChemSpiderID = 388498 | ChemSpiderID_Ref = {{chemspidercite|correct|chemspider}} | UNII = 8021PR16QO | UNII_Ref = {{fdacite|correct|FDA}} | ChEBI = 17394 | ChEBI_Ref = {{ebicite|correct|EBI}} | KEGG = C01047 | smiles = CCNC(=O)CC[C@H](N)C(=O)O | smiles2 = CCNC(=O)CCC(N)C(O)=O | StdInChI = 1S/C7H14N2O3/c1-2-9-6(10)4-3-5(8)7(11)12/h5H,2-4,8H2,1H3,(H,9,10)(H,11,12) | StdInChI_Ref = {{stdinchicite|correct|chemspider}} | StdInChIKey = DATAGRPVKZEWHA-UHFFFAOYSA-N | StdInChIKey_Ref = {{stdinchicite|correct|chemspider}} | synonyms = γ-<small>L</small>-Glutamylethylamide <!-- --> | C=7 | H=14 | N=2 | O=3 | density = | boiling_point = 215 | boiling_notes = <ref name="Pubchem">{{cite web|title=Theanine|url=https://pubchem.ncbi.nlm.nih.gov/compound/439378?from=summary#section=InChI-Key|website=Pubchem Compound|publisher=NCBI|accessdate=21 February 2015}}</ref> | melting_point = 174.20 | melting_notes = <ref name="Pubchem" /> <!-- --> }} '''Theanine''' {{IPAc-en|ˈ|θ|iː|ən|iː|n}}, also known as '''<small>L</small>-γ-glutamylethylamide''' and '''''N''<sup>5</sup>-ethyl-<small>L</small>-glutamine''', is an [[amino acid]] [[Structural analog|analogue]] of the [[proteinogenic amino acid]]s [[glutamic acid|<small>L</small>-glutamate]] and [[glutamine|<small>L</small>-glutamine]] and is found primarily in particular [[phytochemical|plant]] and [[fungi|fungal species]]. It was discovered as a constituent of [[green tea]] in 1949; in 1950, it was isolated from [[gyokuro]] leaves.<ref>{{cite web |url=http://www.ippodo-tea.co.jp/en/tea/gyokuro_02.html |title=Components of Gyokuro| IPPODO |publisher=Ippodo-tea.co.jp |date= |accessdate=2015-05-07 |archive-date=2015-12-23 |archive-url=https://web.archive.org/web/20151223084441/http://www.ippodo-tea.co.jp/en/tea/gyokuro_02.html |url-status=dead }}</ref> Theanine provides a unique jbrothy or savory ([[umami]]) flavor to green tea infusions. The name "'''theanine'''" without a prefix generally implies the [[enantiomer]] '''<small>L</small>-theanine''', which is the form found in tea leaves and as a dietary supplement ingredient. Most studies have used <small>L</small>-theanine. The opposite enantiomer, '''<small>D</small>-theanine''', has been studied less. The regulatory status of theanine varies by country. In Japan, <small>L</small>-theanine has been approved for use in all foods. Restrictions apply to infant foods.<ref name="SAKATO Y. J 1949">SAKATO Y. J. Agri. Chem. Soc. 1949, 23, 262-7</ref><ref>MASON R. Altern. & Complementary Ther. 2001, 7, 91-5</ref> In the United States, the [[Food and Drug Administration]] (FDA) considers it to be [[generally recognized as safe]] (GRAS) and allows its sale as a dietary supplement. The German Federal Institute for Risk Assessment, an agency of their [[Federal Ministry of Food and Agriculture]], objects to the addition of <small>L</small>-theanine to beverages. The [[European Food Safety Authority]] EFSA advised negatively on the use of L-theanine for improving cognitive function, alleviation of psychological stress, maintenance of normal sleep, and reduction of menstrual discomfort.<ref>http://www.efsa.europa.eu/en/efsajournal/pub/2238{{full citation needed|date=May 2017}}</ref> Therefore, health claims for <small>L</small>-theanine are not recognized in the European Union. ==Structure and properties== The chemical name ''N''<sup>5</sup>-ethyl-<small>L</small>-glutamine<ref name = RSC_Chemspider/> and other synonyms (see box) for theanine reflect its chemical structure. The name theanine, without prefix, is generally understood to imply the <small>L</small>- (''S-'') [[enantiomer]], derived from the related [[proteinogenic amino acid|proteinogenic L-amino acid]] [[glutamic acid]]. Theanine is an analog of this amino acid, and its primary [[amide]], <small>L</small>-[[glutamine]] (also a proteinogenic amino acid). Theanine is a derivative of glutamine that is ethylated on the [[amide]] nitrogen (as the name ''N''<sup>5</sup>-ethyl-<small>L</small>-glutamine describes), or alternatively, to the amide formed from [[ethylamine]] and <small>L</small>-glutamic acid at its γ- (5-) side chain [[carboxylic acid]] group (as the name γ-L-glutamylethylamide describes). Relative to theanine, the opposite (<small>D</small>-, ''R-'') enantiomer is largely absent from the literature,<ref name="RSC_Chemspider">{{cite web|url=http://www.chemspider.com/Chemical-Structure.8139819.html?rid=c1b3b94c-9d23-4b66-9b0b-57208603c57a |title=D-theanine &#124; C7H14N2O3 |publisher=ChemSpider.com |date= |accessdate=2015-05-21}}</ref> except implicitly. While natural extracts that are not harshly treated are presumed to contain only the [[biosynthesis|biosynthetic]] <small>L</small>- enantiomeric form, mishandled isolates and racemic chemical preparations of theanines necessarily contain both theanine and its <small>D</small>-enantiomer (and from [[racemic]] syntheses, in equal proportion), and studies have suggested that the <small>D</small>-isomer may actually ''predominate'' in some commercial supplement preparations.<ref>{{cite journal |doi=10.1002/jsfa.4373 |pmid=21735448 |title=L-Theanine: Properties, synthesis and isolation from tea |journal=Journal of the Science of Food and Agriculture |volume=91 |issue=11 |pages=1931–9 |year=2011 |last1=Vuong |first1=Quan V |last2=Bowyer |first2=Michael C |last3=Roach |first3=Paul D }}</ref><ref name="DisomerDesai">{{cite journal |pmid=14755608 |year=2004 |last1=Desai |first1=M. J. |title=Analysis of derivatized and underivatized theanine enantiomers by high-performance liquid chromatography/atmospheric pressure ionization-mass spectrometry |journal=Rapid Communications in Mass Spectrometry |volume=18 |issue=3 |pages=251–6 |last2=Armstrong |first2=D. W. |doi=10.1002/rcm.1319 |bibcode=2004RCMS...18..251D }}</ref> Amino acid [[racemization]] in aqueous media is a well-established chemical process promoted by elevated temperature and non-neutral pH values; prolonged heating of ''Camellia'' extracts—possible for oversteeped teas and in undisclosed commercial preparative processes—has been reported to result in increasing racemization of theanine to give increasing proportions of the nonnatural D-theanine, up to equal proportions of each enantiomer.<ref name="DisomerDesai" /> ==Discovery and distribution== Theanine is found primarily in plant and fungal species. It was discovered as a constituent of tea (''[[Camellia sinensis]])'' in 1949 and in 1950, a laboratory in Kyoto<ref name="SAKATO Y. J 1949"/> successfully isolated it from [[gyokuro]] leaf, which has high theanine content.<ref>{{cite web |url=http://www.ippodo-tea.co.jp/en/tea/gyokuro_03.html |title=How Gyokuro is Processed | IPPODO |publisher=Ippodo-tea.co.jp |date= |accessdate=2015-05-07 |archive-date=2018-04-25 |archive-url=https://web.archive.org/web/20180425233636/http://www.ippodo-tea.co.jp/en/tea/gyokuro_03.html |url-status=dead }}</ref> Theanine is substantially present in black, green, and white [[tea]]s from ''Camellia sinensis'' in quantities of about 1% of the dry weight.<ref>{{cite journal|last1=Finger|first1=Andreas|last2=Kuhr|first2=Susanne|last3=Engelhardt|first3=Ulrich|title=Chromatography of tea constituents|journal=Journal of Chromatography|date=1992|volume=624|issue=1–2|pages=309–310|doi=10.1016/0021-9673(92)85685-M |pmid=1494009}}</ref><ref name="casimir">{{cite journal |doi=10.1016/0006-3002(60)90199-2 |title=Séparation et caractérisation de la N-éthyl-γ-glutamine à partir de ''Xerocomus badius'' |trans-title=Separation and characterization of N-ethyl-γ-glutamine from Xerocomus badius |language=French |year=1960 |last1=Casimir |first1=J. |last2=Jadot |first2=J. |last3=Renard |first3=M. |journal=Biochimica et Biophysica Acta |volume=39 |issue=3 |pages=462–8 |pmid=13808157}}</ref> Deliberately shading tea plants from direct sunlight, as is done for [[matcha]] and [[gyokuro]] green tea, increases L-theanine content.{{citation needed|date=May 2017}} The <small>L</small>-[[enantiomer]]<ref name = RSC_Chemspider/> is the form found in freshly prepared teas and some, but not all, human dietary supplements.<ref name=DisomerDesai/> ==Digestion and metabolism== As a [[structural analog]] of [[glutamate]] and [[glutamine]], the theanine in preparations (teas, pure supplements, etc.) is absorbed in the small intestine after oral ingestion; its hydrolysis to <small>L</small>-glutamate and [[ethylamine]] occur both in the intestine and liver.<ref>{{cite journal |doi=10.1186/2193-1801-2-635 |pmid=24312747 |pmc=3851524 |title=Cystine and theanine: Amino acids as oral immunomodulative nutrients |journal=SpringerPlus |volume=2 |pages=635 |year=2013 |last1=Kurihara |first1=Shigekazu |last2=Shibakusa |first2=Tetsuro |last3=Tanaka |first3=Kenji AK }}</ref> It can also cross the [[blood–brain barrier]] intact, and register pharmacological effects directly.<ref name="yokogoshi">{{cite journal |doi=10.1023/A:1022490806093 |year=1998 |last1=Yokogoshi |first1=Hidehiko |last2=Kobayashi |first2=Miki |last3=Mochizuki |first3=Mikiko |last4=Terashima |first4=Takehiko |journal=Neurochemical Research |volume=23 |issue=5 |pages=667–73 |pmid=9566605 |title=Effect of theanine, γ-glutamylethylamide, on brain monoamines and striatal dopamine release in conscious rats}}</ref> ==Pharmacology== ===Pharmacodynamics=== Theanine is structurally similar to the excitatory neurotransmitter [[glutamate (neurotransmitter)|glutamate]], and in accordance, binds to [[glutamate receptor]]s, though with much lower affinity in comparison. Specifically, it binds to [[ionotropic glutamate receptor]]s in the [[micromolar]] range, including the [[AMPA receptor|AMPA]] and [[kainate receptor]]s and, to a lesser extent, the [[NMDA receptor]].<ref name="nathan">{{cite journal |doi=10.1300/J157v06n02_02 |title=The Neuropharmacology of L-Theanine(N-Ethyl-L-Glutamine) |year=2006 |last1=Nathan |first1=Pradeep |last2=Lu |first2=Kristy |last3=Gray |first3=M. |last4=Oliver |first4=C. |journal=Journal of Herbal Pharmacotherapy |volume=6 |issue=2 |pages=21–30 |pmid=17182482}}</ref><ref name="pmid12596867">{{cite journal | vauthors = Kakuda T, Nozawa A, Sugimoto A, Niino H | title = Inhibition by theanine of binding of [3H]AMPA, [3H]kainate, and [3H]MDL 105,519 to glutamate receptors | journal = Biosci. Biotechnol. Biochem. | volume = 66 | issue = 12 | pages = 2683–6 | year = 2002 | pmid = 12596867 | doi = 10.1271/bbb.66.2683| url = }}</ref><ref name="pmid21477654">{{cite journal | vauthors = Kakuda T | title = Neuroprotective effects of theanine and its preventive effects on cognitive dysfunction | journal = Pharmacol. Res. | volume = 64 | issue = 2 | pages = 162–8 | year = 2011 | pmid = 21477654 | doi = 10.1016/j.phrs.2011.03.010 }}</ref><ref name="pmid12499631">{{cite journal | vauthors = Kakuda T | title = Neuroprotective effects of the green tea components theanine and catechins | journal = Biol. Pharm. Bull. | volume = 25 | issue = 12 | pages = 1513–8 | year = 2002 | pmid = 12499631 | doi = 10.1248/bpb.25.1513 | doi-access = free }}</ref> It acts as an [[receptor antagonist|antagonist]] of the former two sites<ref name="pmid12499631" /> and as an [[agonist]] of the latter site.<ref name="pmid21861094">{{cite journal | vauthors = Wakabayashi C, Numakawa T, Ninomiya M, Chiba S, Kunugi H | title = Behavioral and molecular evidence for psychotropic effects in L-theanine | journal = Psychopharmacology | volume = 219 | issue = 4 | pages = 1099–109 | year = 2012 | pmid = 21861094 | doi = 10.1007/s00213-011-2440-z }}</ref> Theanine also binds to [[Metabotropic glutamate receptor#Group I|group I]] [[metabotropic glutamate receptor|mGluR]]s.<ref name="nathan" /><ref name="pmid15207710">{{cite journal | vauthors = Nagasawa K, Aoki H, Yasuda E, Nagai K, Shimohama S, Fujimoto S | title = Possible involvement of group I mGluRs in neuroprotective effect of theanine | journal = Biochem. Biophys. Res. Commun. | volume = 320 | issue = 1 | pages = 116–22 | year = 2004 | pmid = 15207710 | doi = 10.1016/j.bbrc.2004.05.143 }}</ref> In addition, it inhibits [[glutamine transporter]]s and [[glutamate transporter]]s, and thus blocks the [[reuptake]] of glutamine and glutamate.<ref name="pmid21477654" /><ref name="pmid11325559">{{cite journal | vauthors = Sugiyama T, Sadzuka Y, Tanaka K, Sonobe T | title = Inhibition of glutamate transporter by theanine enhances the therapeutic efficacy of doxorubicin | journal = Toxicol. Lett. | volume = 121 | issue = 2 | pages = 89–96 | year = 2001 | pmid = 11325559 | doi = 10.1016/s0378-4274(01)00317-4 }}</ref><ref name="pmid14643924">{{cite journal | vauthors = Sugiyama T, Sadzuka Y | title = Theanine and glutamate transporter inhibitors enhance the antitumor efficacy of chemotherapeutic agents | journal = Biochim. Biophys. Acta | volume = 1653 | issue = 2 | pages = 47–59 | year = 2003 | pmid = 14643924 | doi = 10.1016/s0304-419x(03)00031-3 }}</ref> Lastly, theanine elicits [[umami]] taste, and this effect has been found to be a consequence of the fact that it directly binds to and activates the [[TAS1R1|T1R1]] + [[TAS1R3|T1R3]] [[heterodimer]] or [[Umami#Taste receptors|umami (savory) taste receptor]].<ref name="pmid24633359">{{cite journal | vauthors = Narukawa M, Toda Y, Nakagita T, Hayashi Y, Misaka T | title = L-Theanine elicits umami taste via the T1R1 + T1R3 umami taste receptor | journal = Amino Acids | volume = 46 | issue = 6 | pages = 1583–7 | year = 2014 | pmid = 24633359 | doi = 10.1007/s00726-014-1713-3 }}</ref> Theanine increases [[serotonin]], [[dopamine]], [[GABA]], and [[glycine]] levels in various areas of the brain, as well as [[brain-derived neurotrophic factor|BDNF]] and [[nerve growth factor|NGF]] levels in certain brain areas.<ref name="nathan" /><ref name="pmid21861094" /><ref name="pmid17904164">{{cite journal | vauthors = Yamada T, Terashima T, Wada K, Ueda S, Ito M, Okubo T, Juneja LR, Yokogoshi H | title = Theanine, r-glutamylethylamide, increases neurotransmission concentrations and neurotrophin mRNA levels in the brain during lactation | journal = Life Sci. | volume = 81 | issue = 16 | pages = 1247–55 | year = 2007 | pmid = 17904164 | doi = 10.1016/j.lfs.2007.08.023 }}</ref><ref name="pmid9566605">{{cite journal | vauthors = Yokogoshi H, Kobayashi M, Mochizuki M, Terashima T | title = Effect of theanine, r-glutamylethylamide, on brain monoamines and striatal dopamine release in conscious rats | journal = Neurochem. Res. | volume = 23 | issue = 5 | pages = 667–73 | year = 1998 | pmid = 9566605 | doi = 10.1023/A:1022490806093| url = }}</ref> However, its effect on serotonin is still a matter of debate in the scientific community, with studies showing increases and decreases in brain serotonin levels using similar experimental protocols.<ref name="yokogoshi" /><ref>{{cite journal |doi=10.1271/bbb.62.816 |title=Theanine-induced Reduction of Brain Serotonin Concentration in Rats |year=1998 |last1=Yokogoshi |first1=Hidehiko |last2=Mochizuki |first2=Mikiko |last3=Saitoh |first3=Kotomi |journal=Bioscience, Biotechnology, and Biochemistry |volume=62 |issue=4 |pages=816–7 |pmid=9614715}}</ref> It has also been found that injecting spontaneously hypertensive mice with theanine significantly lowered levels of 5-hydroxy[[indole]]s in the brain.<ref name="yokogoshi-5hydroxyindoles">{{cite journal |doi=10.1271/bbb.59.615 |title=Reduction Effect of Theanine on Blood Pressure and Brain 5-Hydroxyindoles in Spontaneously Hypertensive Rats |year=1995 |last1=Yokogoshi |first1=Hidehiko |last2=Kato |first2=Yukiko |last3=Sagesaka |first3=Yuko M. |last4=Takihara-Matsuura |first4=Takanobu |last5=Kakuda |first5=Takami |last6=Takeuchi |first6=Naokazu |journal=Bioscience, Biotechnology, and Biochemistry |volume=59 |issue=4 |pages=615–8 |pmid=7539642}}</ref> Researchers also speculate that it may inhibit [[glutamate]] [[excitotoxicity]].<ref name="nathan" /> ===Effects=== Able to cross the [[blood–brain barrier]], theanine has reported [[psychoactive drug|psychoactive]] properties.<ref name="gomez">{{cite journal |doi=10.1097/01.WNF.0000240940.13876.17 |title=The Deployment of Intersensory Selective Attention |year=2007 |last1=Gomez-Ramirez |first1=Manuel |last2=Higgins |first2=Beth A. |last3=Rycroft |first3=Jane A. |last4=Owen |first4=Gail N. |last5=Mahoney |first5=Jeannette |last6=Shpaner |first6=Marina |last7=Foxe |first7=John J. |journal=Clinical Neuropharmacology |volume=30 |pages=25–38 |pmid=17272967 |issue=1}}</ref> Theanine has been studied for its potential ability to reduce mental and physical [[Stress (medicine)|stress]],<ref name="kimura">{{cite journal |doi=10.1016/j.biopsycho.2006.06.006 |title=L-Theanine reduces psychological and physiological stress responses |year=2007 |last1=Kimura |first1=Kenta |last2=Ozeki |first2=Makoto |last3=Juneja |first3=Lekh Raj |last4=Ohira |first4=Hideki |journal=Biological Psychology |volume=74 |pages=39–45 |pmid=16930802 |issue=1}}</ref> improve cognition,<ref>{{cite journal |doi=10.1089/jmf.2009.1374 |title=A Combination of Green Tea Extract andl-Theanine Improves Memory and Attention in Subjects with Mild Cognitive Impairment: A Double-Blind Placebo-Controlled Study |year=2011 |last1=Park |first1=Sang-Ki |last2=Jung |first2=In-Chul |last3=Lee |first3=Won Kyung |last4=Lee |first4=Young Sun |last5=Park |first5=Hyoung Kook |last6=Go |first6=Hyo Jin |last7=Kim |first7=Kiseong |last8=Lim |first8=Nam Kyoo |last9=Hong |first9=Jin Tae |last10=Ly |first10=Sun Yung |last11=Rho |first11=Seok Seon |journal=Journal of Medicinal Food |volume=14 |issue=4 |pages=334–43 |pmid=21303262|display-authors=8 }}</ref> and boost mood and cognitive performance in a synergistic manner with [[caffeine]].<ref name="pmid18006208">{{cite journal |doi=10.1016/j.biopsycho.2007.09.008 |title=The effects of l-theanine, caffeine and their combination on cognition and mood |year=2008 |last1=Haskell |first1=Crystal F. |last2=Kennedy |first2=David O. |last3=Milne |first3=Anthea L. |last4=Wesnes |first4=Keith A. |last5=Scholey |first5=Andrew B. |journal=Biological Psychology |volume=77 |issue=2 |pages=113–22 |pmid=18006208}}</ref><ref>{{cite journal |url=http://www.sciencenews.org/view/generic/id/8965/description/Distracted_Tea_might_help_your_focus |title=Distracted? Tea might help your focus |date=September 29, 2007 |first1=Janet |last1=Raloff |journal=Science News |volume=172 |issue=13 |page=206 |doi=10.1002/scin.2007.5591721319}}</ref><ref name="own" /><ref>{{cite journal |doi=10.1016/j.appet.2010.01.003 |title=L-Theanine and caffeine improve task switching but not intersensory attention or subjective alertness |year=2010 |last1=Einöther |first1=Suzanne J.L. |last2=Martens |first2=Vanessa E.G. |last3=Rycroft |first3=Jane A. |last4=De Bruin |first4=Eveline A. |journal=Appetite |volume=54 |issue=2 |pages=406–9 |pmid=20079786}}</ref><ref>{{cite journal |doi=10.1179/147683010X12611460764840 |title=The combination of L-theanine and caffeine improves cognitive performance and increases subjective alertness |year=2010 |last1=Giesbrecht |first1=T. |last2=Rycroft |first2=J.A. |last3=Rowson |first3=M.J. |last4=De Bruin |first4=E.A. |journal=Nutritional Neuroscience |volume=13 |issue=6 |pages=283–90 |pmid=21040626}}</ref><ref>{{cite journal |pmid=18641209 |year=2008 |last1=Kelly |first1=Simon P. |last2=Gomez-Ramirez |first2=Manuel |last3=Montesi |first3=Jennifer L. |last4=Foxe |first4=John J. |title=L-theanine and caffeine in combination affect human cognition as evidenced by oscillatory alpha-band activity and attention task performance |volume=138 |issue=8 |pages=1572S–1577S |journal=The Journal of Nutrition |url=http://jn.nutrition.org/cgi/pmidlookup?view=long&pmid=18641209|doi=10.1093/jn/138.8.1572S |doi-access=free }}</ref>{{update inline|date=March 2020}} A [[Natural Standard]] monograph that reviews current research on theanine reports that it is likely safe in doses of 200–250&nbsp;mg up to a maximum daily dose of 1,200&nbsp;mg. Though some people use theanine for these purposes, Natural Standard rates the evidence to support the usage for anxiety reduction, blood pressure control, and mood improvement as "unclear or conflicting scientific evidence" and the evidence for improved cognition as "fair negative scientific evidence". Many of the studies of theanine were done in combination with caffeine as found in tea. While the studies found that the combination had some effect on mood, the studies found that theanine alone had little effect.<ref>{{cite web|title=Theanine Monograph |url=https://naturalmedicines.therapeuticresearch.com/databases/food,-herbs-supplements/t/theanine/professional.aspx |website=Natural Standard |accessdate=30 October 2014 |url-status=dead |archiveurl=https://web.archive.org/web/20141224082503/https://naturalmedicines.therapeuticresearch.com/databases/food,-herbs-supplements/t/theanine/professional.aspx |archivedate=December 24, 2014 }}</ref> A review by other researchers of a small set of trials concluded that there are benefits of L-theanine in reducing acute stress and anxiety in people with stressful conditions.<ref>{{Cite journal|last1=Everett|first1=J.M.|last2=Gunathilake|first2=D.|last3=Dufficy|first3=L.|last4=Roach|first4=P.|last5=Thomas|first5=J.|last6=Upton|first6=D.|last7=Naumovski|first7=N.|title=Theanine consumption, stress and anxiety in human clinical trials: A systematic review|journal=Journal of Nutrition & Intermediary Metabolism|volume=4|pages=41–42|doi=10.1016/j.jnim.2015.12.308|year=2016|doi-access=free}}</ref> ==Supplement use== In 2001, the German Federal Institute for Risk Assessment (''Bundesinstitut für Risikobewertung'', BfR) objected to the addition of isolated theanine to beverages.<ref>https://www.bfr.bund.de/cm/343/getraenke_mit_isoliertem_l_theanin.pdf</ref><ref name="KanarekLieberman2011">{{cite book|author1=Robin B. Kanarek|author2=Harris R. Lieberman|title=Diet, Brain, Behavior: Practical Implications|url=https://books.google.com/books?id=uTmyN1g5JgwC&pg=PA239|date=6 October 2011|publisher=CRC Press|isbn=978-1-4398-2156-5|pages=239–}}</ref> The institute stated the amount of theanine consumed by regular drinkers of tea or coffee is virtually impossible to determine. While it was estimated the quantity of [[green tea]] consumed by the average Japanese tea drinker per day contains about 20&nbsp;mg of the substance, there are no studies measuring the amount of theanine being extracted by typical preparation methods, or the percentage lost by discarding the first infusion. Therefore, with the Japanese being exposed to possibly much less than 20&nbsp;mg per day, and Europeans presumably even less, it was the opinion of the BfR that [[pharmacological]] reactions to drinks typically containing 50&nbsp;mg of theanine per 500 milliliters could not be excluded—reactions such as impairment of [[Psychomotor learning|psychomotor]] skills and amplification of the [[sedating]] effects of alcohol and [[hypnotics]].<ref name="BfR">{{cite web |url=http://www.bfr.bund.de/cm/208/getraenke_mit_isoliertem_l_theanin.pdf |title=Getränke mit isoliertem L-Theanin |trans-title=Beverages with isolated L-theanine |publisher=Bundesinstitut für Risikobewertung |language=German |date=August 2003 |access-date=2020-07-06 |archive-date=2010-10-11 |archive-url=https://web.archive.org/web/20101011120727/http://www.bfr.bund.de/cm/208/getraenke_mit_isoliertem_l_theanin.pdf |url-status=dead }}</ref> In 2006, a study found no consistent, statistically significant treatment-related adverse effects on behavior, morbidity, mortality, body weight, food consumption and efficiency, clinical chemistry, [[hematology]], or [[urinalysis]] in rats fed high doses of theanine for 13 weeks.<ref name="borzelleca">{{cite journal |doi=10.1016/j.fct.2006.03.014 |title=A 13-week dietary toxicity and toxicokinetic study with l-theanine in rats |year=2006 |last1=Borzelleca |first1=J.F. |last2=Peters |first2=D. |last3=Hall |first3=W. |journal=[[Food and Chemical Toxicology]] |volume=44 |issue=7 |pages=1158–66 |pmid=16759779}}</ref> Large studies in humans have not been undertaken; however, several smaller-scale studies (fewer than 100 participants) have shown increased alpha wave generation and lowered anxiety, along with benefits to sleep quality in people with ADHD.<ref name="kimura" /><ref name="Lyon">{{cite journal|pmid=22214254|year=2011|last1=Lyon|first1=Michael R.|last2=Kapoor|first2=Mahendra P. |last3=Juneja|first3=Lekh R.|title=The effects of L-theanine (Suntheanine®) on objective sleep quality in boys with attention deficit hyperactivity disorder (ADHD): a randomized, double-blind, placebo-controlled clinical trial|volume=16|issue=4|pages=348–54|journal=Alternative Medicine Review |url=http://www.altmedrev.com/publications/16/4/348.pdf|archive-url=https://web.archive.org/web/20171118181912/http://www.altmedrev.com/publications/16/4/348.pdf|archive-date=2017-11-18|url-status=dead}}</ref><ref name="koboyashi">{{cite journal |doi=10.1271/nogeikagaku1924.72.153 |title=L-テアニンのヒトの脳波に及ぼす影響 |trans-title=Effects of L-Theanine on the Release of α-Brain Waves in Human Volunteers |language=Japanese |year=1998 |last1=Kobayashi |first1=Kanari |last2=Nagato |first2=Yukiko |last3=Aoi |first3=Nobuyuki |last4=Juneja |first4=Lekh Raj |last5=Kim |first5=Mujo |last6=Yamamoto |first6=Takehiko |last7=Sugimoto |first7=Sukeo |journal=Journal of the Agricultural Chemical Society of Japan |volume=72 |issue=2 |pages=153–7|doi-access=free }}</ref> The combination of theanine and [[caffeine]] has been shown to promote faster simple reaction time, faster numeric working memory reaction time and improved sentence verification accuracy.<ref name="pmid18006208" /><ref name="own">{{cite journal |doi=10.1179/147683008X301513 |title=The combined effects of L-theanine and caffeine on cognitive performance and mood |year=2008 |last1=Owen |first1=Gail N. |last2=Parnell |first2=Holly |last3=De Bruin |first3=Eveline A. |last4=Rycroft |first4=Jane A. |journal=Nutritional Neuroscience |volume=11 |issue=4 |pages=193–8 |pmid=18681988}}</ref><ref name="Bryan">{{cite journal |doi=10.1111/j.1753-4887.2007.00011.x |title=Psychological effects of dietary components of tea: Caffeine and L-theanine |year=2008 |last1=Bryan |first1=Janet |journal=Nutrition Reviews |volume=66 |issue=2 |pages=82–90 |pmid=18254874}}</ref><ref name="kelly">{{cite journal |first1=Simon P. |last1=Kelly |first2=Manuel |last2=Gomez-Ramirez |first3=Jennifer L. |last3=Montesi |first4=John J. |last4=Foxe |title=L-Theanine and Caffeine in Combination Affect Human Cognition as Evidenced by Oscillatory alpha-Band Activity and Attention Task Performance |journal=The Journal of Nutrition |pmid=18641209 |url=http://jn.nutrition.org/cgi/pmidlookup?view=long&pmid=18641209 |year=2008 |volume=138 |issue=8 |pages=1572S–1577S|doi=10.1093/jn/138.8.1572S |doi-access=free }}</ref> Theanine has been reported to raise levels of brain serotonin, dopamine, and GABA, with possible improvement in specific memory and learning tasks.<ref>{{cite journal|title=The neuropharmacology of L-theanine(N-ethyl-L-glutamine): a possible neuroprotective and cognitive enhancing agent |date=2015-04-20 |pmid=17182482 |doi=10.1300/J157v06n02_02 |volume=6 |issue=2 |journal=J Herb Pharmacother |pages=21–30 | last1 = Nathan | first1 = PJ | last2 = Lu | first2 = K | last3 = Gray | first3 = M | last4 = Oliver | first4 = C}}</ref> ==In brewed teabags== A study of teabags sold in British supermarkets in 2011 found that the teabags containing the most <small>L</small>-theanine per cup (24&nbsp;mg versus 8&nbsp;mg per cup) were the lower-quality brands containing black tea, with a supermarket brand of black tea having the highest theanine content. The study demonstrates that brewing time is a major determinant of the amount of l-theanine extracted. Addition of sugar and small quantities of milk make no significant difference, while larger quantities of milk reduced the measured theanine content.<ref>{{cite journal |doi=10.1016/j.foodchem.2010.08.071 |title=How much theanine in a cup of tea? Effects of tea type and method of preparation |journal=Food Chemistry |volume=125 |issue=2 |pages=588 |year=2011 |last1=Keenan |first1=Emma K. |last2=Finnie |first2=Mike D.A. |last3=Jones |first3=Paul S. |last4=Rogers |first4=Peter J. |last5=Priestley |first5=Caroline M. }}</ref> ==See also== * [[gamma-Glutamylmethylamide|''gamma''-Glutamylmethylamide]] * [[Green tea]] ==References== '''Notes''' {{Reflist}} '''Further reading''' * {{cite journal |author1=E.K. Keenan |author2=M.D.A. Finnie |author3=P.S. Jones |author4=P.J. Rogers |author5=C.M. Priestley |date=2011 |title=How much theanine in a cup of tea? Effects of tea type and method of preparation |journal=Food Chemistry |volume=125 |issue=2 |pages=588–594 |doi=10.1016/j.foodchem.2010.08.071}} * {{cite journal |author1=Y. Orihara |author2=T. Furuya |date=1990 |title=Production of theanine and other γ-glutamyl derivatives by ''Camellia sinensis'' cultured cells |journal=Plant Cell Reports |volume=9 |issue=2 |pages=65–68 |doi=10.1007/BF00231550 |pmid=24226431}} {{Glutamate receptor modulators}} {{Glutamate metabolism and transport modulators}} [[Category:Non-proteinogenic amino acids]] [[Category:Anxiolytics]] [[Category:Carboxamides]] [[Category:AMPA receptor antagonists]] [[Category:Kainate receptor antagonists]] [[Category:NMDA receptor agonists]] [[Category:Excitatory amino acid reuptake inhibitors]] <noinclude> <small>This page was moved from [[:en:Theanine]]. Its edit history can be viewed at [[Theanine/edithistory]]</small></noinclude> 2z69udtkafnoatz84vwse98obqwmwqv Y-Control for fighters 0 113824 769786 690847 2026-10-22T19:36:58Z Testvinca31 47963 /* growthexperiments-addlink-summary-summary:1|1|0 */ 769786 wikitext text/x-wiki {{Use dmy dates|date=September 2019}} {{Multiple issues| {{inadequate lead|date=April 2019}} {{sections|date=April 2019}} }} The '''Y-Control System''' is a [[Radio guidance|radio]] [[guidance system]]. Test. == The Y-Control Fighter Guidance System == By late 1943 the Luftwaffe was facing multiple problems in navigation and control of its assets [[Combined Bomber Offensive|in the European airspace]]. [[Radio jamming|Allied jamming]] of existing VHF voice radio links and MF navigation beacons was becoming extremely effective, At the same time training of pilots was being curtailed by the lack of fuel. This resulted in fighter formations being unable to find the allied bombers and frequently getting lost. Work was then carried out with regards to solving these issues. Part of the research resulted in the radio systems such a '''[[Luftwaffe radio equipment (Funkgerät) of World War II|Hermine]]''' and '''[[Luftwaffe radio equipment (Funkgerät) of World War II|Bernhard]]'''. However a simpler system that could be rolled out faster and was usable by minimum hour pilots in single seat fighters was also developed.<ref>{{cite web |author=Jan-Martin Noeding |url=http://www.noding.com/la8ak/el.htm |title=Luftwaffe radio equipment |publisher=Noding.com |date=2005-03-25 |accessdate=2019-04-09 |archive-url=https://web.archive.org/web/20181205211806/http://www.noding.com/la8ak/el.htm |archive-date=2018-12-05 |url-status=live}}</ref> This was the '''Y-Control System'''. It was based around the work done for the Y-Gerät system of bomber guidance. There were differences in frequency and a dedicated transponder was not required. Initially it used a modified '''FuG17E''' radio but this was soon replaced by an add on to the standard radio FuG16Z turning it into the '''FuG16ZY'''.<ref>{{cite web|url=https://www.dropbox.com/s/yzdqk4wrhxz5ufc/ADIK527_Y_Site_Equipment.pdf?dl=0|title= Y Site Equipment}}</ref> The system worked by using sites known as Y-Stations. Each station had 5 radio operation systems. Each consisted of an omnidirectional transmitter an omnidirectional receiver and a direction finder. This allowed each site to control 5 fighters. The transmitter would send out a signal which was picked up by the '''FuG16ZY''' in [[The Fighter|the fighter]] (known as the Y Fighter), this repeated the signal back on a frequency 1.9&nbsp;MHz lower than the transmitted frequency. Using the direction finder (DF) the angle was measured. Range was calculated by a timing system connected to both the transmitter and the omnidirectional receiver. Height could not be measured. However voice could be transposed onto the ranging signal allowing the ground controller to talk and listen to the pilot of the plane he was controlling, hence the pilot could report altitude when requested to do so. Controlling a single fighter was of not much use in practice so the Luftwaffe developed group control, where a Y-Fighter was part of a group of fighters intercepting an allied bomber stream, The Y-Fighter was painted a distinctive colour and the rest of the flight simple followed him. The flight leader could also listen into the ground controller channel and hear what the ground controller was saying while also being able to talk to the flight. The Y-Fighter was never the group controller. the system was susceptible to jamming on the '''FuG16ZY''' wavelength but was at least partially usable for the rest of the war. Controllable range was approx 250&nbsp;km depending on aircraft height. One source mentions that relay stations could be used to extend the radio range. The relay station would consist of a single transmitter/receiver/DF finder system without the rest of the communication and guidance systems of the main Y site. The radio system used was a modified '''FuG16''' radio. The Y-Site also contained other systems such as radio communications for talking to area control.<ref>{{cite web |url=http://www.cdvandt.org |title=ADIK reports 1944-1945 |publisher=Cdvandt.org |date= |accessdate=2019-04-09 |archive-url=https://web.archive.org/web/20190417162309/http://www.cdvandt.org/ |archive-date=2019-04-17 |url-status=live}}</ref> The system was usually used to control groups of day fighters intercepting American bomber streams but it could be used to guide individual night fighters.{{Citation needed|date=September 2019}} ==References== {{Reflist}} [[Category:Aerial warfare tactics]] [[Category:Avionics]] [[Category:Military radio systems]] [[Category:Radio navigation]] [[Category:World War II German electronics]] <noinclude> <small>This page was moved from [[:en:Y-Control for fighters]]. Its edit history can be viewed at [[Y-Control for fighters/edithistory]]</small></noinclude> 0exf8qh0e1u1lm4u1av6smi5hfobae2 Autolib' 0 114052 769784 763722 2026-10-22T19:34:36Z Testvinca31 47963 769784 wikitext text/x-wiki {{update|date=December 2017}} {{Use dmy dates|date=July 2013}} {{Infobox company | name = Autolib' | logo = [[File:Autolib logo.svg|frameless]] | caption = | type = Public | genre = | fate = | predecessor = | successor = | foundation = {{Start date|2011|12}} (Paris)<br/>{{Start date|2013|10}} (Lyon)<br/>{{Start date|2014|01}} (Bordeaux) | founder = | defunct = {{End date|2018|07|31}} | location_city = [[Paris]] | location_country = [[France]] | location = | locations = | area_served = Paris, [[Bordeaux]] and [[Lyon]] | key_people = | industry = [[Car rental]] | products = | services = [[Carsharing]] | revenue = | operating_income = | net_income = | aum = | assets = | equity = | owner = | num_employees = | parent = [[Bolloré]] | divisions = | subsid = | homepage = {{URL|autolib.eu}}<br>{{URL|autolibmetropole.fr}} }} '''Autolib'''' was an [[electric car|electric]] [[car sharing]] service which was inaugurated in [[Paris]], France, in December 2011. It closed on July 31st 2018.<ref name=website>https://www.autolib.eu/</ref> It was operated by the [[Bolloré]] industrial group, and complemented the city's [[bike sharing]] scheme, [[Velib']], which was set up in 2007. The Autolib' scheme maintained a fleet of [[electric car|all-electric]] [[Bolloré Bluecar]]s for public use on a paid subscription basis, employing a citywide network of parking and [[charging station]]s.<ref name=Econom0911>{{cite news|url=http://www.economist.com/node/21528681?frsc=dg|title=All charged up for sharing|work=[[The Economist]]|date=10 September 2011|accessdate=11 September 2011}}</ref><ref>[https://www.google.com/hostednews/afp/article/ALeqM5gRjBY0fNQ1aBoJrGt9N1pYfekzwQ?docId=CNG.b55c97688ff9e8fbe0e4915e511e1a6e.211 "Autolib' in the Paris region: dissenting voices before the official launch"]. AFP via Google. 20 November 2011. Retrieved 10 July 2013.</ref> {{As of|2016|07|03}}, 3,980 Bluecars had been registered for the service, and the scheme had more than 126,900 registered subscribers;<ref name=Fleet092013/><ref name=GuardJul14>{{cite web|url=https://www.theguardian.com/cities/2014/jul/09/electric-boris-car-source-london-how-work-paris-autolib|title=Electric 'Boris cars' are coming to London – how do they work in Paris?|work=[[The Guardian]]|date=9 July 2014|accessdate=23 February 2015}}</ref> Autolib' furthermore offered 1,084 electric car stations in Paris agglomeration with 5,935 charging points.<ref name=LeFigaro022013/><ref>{{cite web|url=https://drive.google.com/file/d/0B8MFxB5YvOOkd3VYZm54cDJJS0U/view?usp=drive_web|title=Tableau de bord du 3 juillet 2016|work=Autolib' Métropole|date=3 July 2016|accessdate=24 July 2016}}.</ref> Since beginning operations in Paris, Autolib' expanded its business to the cities of [[Lyon]] and [[Bordeaux]].<ref name=TomorrowTheWorld/><ref name=BordBluecub>{{cite web|url=http://www.lesechos.fr/industrie-services/automobile/0203232487832-bollore-inaugure-ses-bluecub-a-bordeaux-642008.php#|title=Bolloré inaugure ses Bluecub à Bordeaux|publisher=LesEchos.fr|date=10 January 2014|accessdate=24 February 2015|archive-url=https://web.archive.org/web/20150224074030/http://www.lesechos.fr/industrie-services/automobile/0203232487832-bollore-inaugure-ses-bluecub-a-bordeaux-642008.php|archive-date=24 February 2015|url-status=dead}} {{Webarchive|url=https://web.archive.org/web/20150224074030/http://www.lesechos.fr/industrie-services/automobile/0203232487832-bollore-inaugure-ses-bluecub-a-bordeaux-642008.php |date=24 February 2015 }}</ref> Bolloré also signed deals to begin operating offshoots of Autolib' in [[London]] and [[Indianapolis]] in 2015<ref name=GuardJul14/><ref name=Indianapolis>{{cite web|url=http://green.autoblog.com/2013/06/13/french-car-sharing-service-autolib-will-make-us-debut-in-indiana/|title=French car-sharing service Autolib will make US debut in Indianapolis|publisher=AOL AutoBlog Green|date=13 June 2013|accessdate=28 June 2013}}</ref><ref name=Indianapolis2>{{cite web|url=http://www.autoblog.com/2014/05/21/bluecar-car-sharing-affiliate-will-debut-in-indianapolis-early-n/|title=BlueCar car-sharing affiliate will debut in Indianapolis early next year|publisher=AOL AutoBlog|date=21 May 2014|accessdate=17 February 2015}}</ref>, [[Turin]] in 2016 and [[Singapore]] in 2017.<ref name=StraitsTimes5000/> ==History== The Autolib' system was a follow-up to Paris' successful [[Velib']] [[bike sharing]] scheme, which began operations in 2007. The system's electric cars were supplied by the [[Bolloré]] industrial group, as the result of a collaboration with the Italian automotive firm [[Pininfarina]].<ref name=bikeradar>{{cite web|url=http://www.bikeradar.com/news/article/move-over-velib-autolib-is-on-its-way-17274|title=Move over Velib, Autolib is on its way|author=Mark Appleton|publisher=Bike Radar|date=30 June 2008|accessdate=21 January 2012|archive-url=https://web.archive.org/web/20120214051903/http://www.bikeradar.com/news/article/move-over-velib-autolib-is-on-its-way-17274/|archive-date=14 February 2012|url-status=dead}} {{Webarchive|url=https://web.archive.org/web/20120214051903/http://www.bikeradar.com/news/article/move-over-velib-autolib-is-on-its-way-17274/ |date=14 February 2012 }}</ref> There were also plans to integrate payment for the [[bicycle]] and car hire schemes with the ticketing systems for traditional modes of [[public transport]].<ref name=independent>{{cite news|url=https://www.independent.co.uk/environment/green-living/boris-jumps-on-board-frances-hire-an-electric-car-scheme-1635137.html |work=The Independent | location=London | title=Boris jumps on board France's 'hire an electric car' scheme | first=Michael |last=McCarthy | date=2 March 2009 | accessdate=27 May 2010 }}</ref> In May 2012, [[Vincent Bolloré]], the head of the Bolloré group, stated that he expected Autolib' to become profitable by 2018<ref>{{cite web|url=http://www.michelinchallengebibendum.com/en/NEWS-AND-PUBLICATIONS/News-and-publications/Bollore-s-BlueCar-could-break-even-by-2018|title=Bolloré’s BlueCar could break even by 2018|publisher=[[Challenge Bibendum]]|date=31 May 2012|accessdate=5 June 2013}}{{Dead link|date=August 2022 |bot=InternetArchiveBot |fix-attempted=yes }}</ref>, but the service ended on 31 July 2018 and was replaced on 2 December 2018 by a municipal service to manage the 1000 electrical charging stations in Paris and the City of Paris concluded agreements with several carsharing societies: three freefloating operators and four additional ones participating to the new service Mobilib'.<ref>{{cite web|language=fr-FR |publisher=City of Paris |title=Véhicules partagés |url=https://www.paris.fr/pages/vehicules-partages-4541 |date=25 May 2020 |accessdate=26 June 2020}}</ref> [[File:Paris Autolib 06 2012 Bluecar 2905.JPG|thumb|left|Bolloré Bluecars recharging at an Autolib' service kiosk on Rue du Quatre Septembre, Paris, in June 2012.]] Construction of the Autolib' stations began in mid-2011, and 66 of the scheme's Bolloré Bluecars were deployed for a two-month preliminary [[trial]] period between October and December 2011.<ref name=Econom0911/><ref>{{cite news|url=https://www.nytimes.com/2011/10/04/business/global/paris-tests-short-term-rentals-of-electric-cars.html?_r=1&src=recg|title=Paris Tests Short-Term Rentals of Electric Cars |author=David Jolly |work=[[The New York Times]]|date=3 October 2011|accessdate=5 October 2011 }}</ref> The system entered service on 5 December 2011, with an initial fleet of 250 Bluecars and 250 Autolib’ rental stations serving the city of Paris and 18 surrounding communities (96 in 2016), grouped into the syndicate of associated collectivities "Autolib' Métropole".<ref>{{cite web|url=http://www.autolibmetropole.fr/autolib-metropole/qui-sommes-nous/|title=Autolib' Métropole, Qui sommes-nous ?|work=Autolib' Métropole|accessdate=24 July 2016}}.</ref> At the scheme's inception, car availability was a problematic issue, as more Parisians than expected subscribed to the service. Moreover, by early January 2012, up to 40 of the 250 cars in the initial fleet had been temporarily withdrawn from service to repair vandalism or malfunctions.<ref>{{cite news|url=http://www.lefigaro.fr/actualite-france/2012/01/02/01016-20120102ARTFIG00265-autolib-deja-victime-de-pannes-et-de-vandalisme.php|title=Autolib' déjà victime de pannes et de vandalisme|trans-title=Autolib' already suffering breakdowns and vandalism|language=French|work=[[Le Figaro]]|date=2 January 2012|accessdate=21 January 2012}}</ref><ref>{{cite web|url=http://green.autoblog.com/2012/01/13/parisian-autolib-car-sharing-service-suffers-setbacks-sells-6-0/|title=Parisian Autolib car sharing service suffers setbacks, sells 6,000 subscriptions |author=Domenick Yoney|publisher=[[Autoblog Green]]|date=13 January 2012|accessdate=21 January 2012}}</ref> By July 2012, 650 parking and [[charging station]]s had been deployed around Paris and the 46 [[Commune (administrative division)|communes]] participating in the scheme,<ref name=LP1012/> and by February 2013 there were 4,000 charging points.<ref name=LeFigaro022013/> The program's user base grew from 6,000 subscribers at the end of December 2011 to 27,000 in July 2012, and reached 37,000 by early October 2012, of which 13,000 had an annual subscription.<ref name=LP1012>{{cite news|url=http://www.leparisien.fr/transports/autolib/bollore-lance-la-bluecar-en-region-parisienne-05-10-2012-2207469.php|title=Bolloré lance la "BlueCar" en région parisienne|language=French|trans-title=Bolloré launches "BlueCar" in the Paris region|author=AFC and Le Parisien|work=[[Le Parisien]]|date=5 October 2012|accessdate=12 October 2012}}</ref><ref>{{cite news|url=http://www.francesoir.fr/pratique/transport/autolib-plus-6000-abonnes-en-deux-semaines-166505.html|title=Autolib' : Plus de 6.000 abonnés en deux semaines|trans-title=Autolib' : More than 6,000 subscribers in two weeks|language=French|work=[[France Soir]]|date=2 January 2012|accessdate=21 January 2012|archive-date=15 January 2012|archive-url=https://web.archive.org/web/20120115134646/http://www.francesoir.fr/pratique/transport/autolib-plus-6000-abonnes-en-deux-semaines-166505.html|url-status=dead}} {{Webarchive|url=https://web.archive.org/web/20120115134646/http://www.francesoir.fr/pratique/transport/autolib-plus-6000-abonnes-en-deux-semaines-166505.html |date=15 January 2012 }}</ref><ref name=LesEchos>{{cite news|url=http://m.lesechos.fr/transports/paris-veut-eviter-le-changement-de-nom-d-autolib-0202185513768.htm|title=Paris veut éviter le changement de nom d'Autolib'|language=French|trans-title=Paris wants to avoid Autolib name change|author=Marion Kindermans|work=Les Échos (France)|date=23 July 2012|accessdate=30 July 2012}}{{Dead link|date=October 2025 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> [[File:Autolib' rental station Paris 02.jpg|thumb|An Autolib' rental station in 2013.]] During 2012, sales of [[electric cars in France]] were led by the Bolloré Bluecar deployed for Autolib', with 1,543 units registered, representing 28% of total all-electric cars registered in the country that year.<ref>{{cite web|url=http://www.avem.fr/actualite-voitures-electriques-le-bilan-des-immatriculations-2012-en-france-3770.html|title= Voitures électriques – Le bilan des immatriculations 2012 en France|language=French|trans-title=Electric Cars – The balance of registrations in France 2012|author=Michaël Torregrossa|publisher= Association pour l'Avenir du Véhicule Electrique Méditerranéen (AVEM)|date=19 January 2013|accessdate=16 March 2013}}</ref> Over 2,000 Bolloré Bluecars had been registered for Autolib' by September 2013.<ref name=Fleet092013>{{cite web|url=http://www.avem.fr/actualite-paris-autolib-passe-le-seuil-des-3-millions-de-locations-4493.html|title=Paris – Autolib’ passe le seuil des 3 millions de locations|trans-title=Paris – Autolib' passes the threshold of 3 million rentals|author=Michaël Torregrossa|publisher=Association pour l'Avenir du Véhicule Electrique Méditerranéen (AVEM)|date=19 October 2013|accessdate=21 October 2013|language=French}}</ref><ref name=Launch2>{{cite news|url=http://veja.abril.com.br/noticia/ciencia/a-revolucao-do-autolib-em-paris|title=A revolução do Autolib' em Paris|author=Fernando Valeika de Barros|work=[[Veja (magazine)|Veja]]|date=10 December 2011|accessdate=17 December 2011|language=Portuguese}}</ref> By late September 2012, Autolib's fleet reached the milestone of 500,000 rentals since its launch,<ref name=LP1012/><ref name=GCR1012>{{cite web|url=http://www.greencarreports.com/news/1079516_bollore-bluecar-sharing-pariss-most-popular-electric-car|title=Bollore Bluecar: Sharing Paris's Most Popular Electric Car |author=John Voelcker |publisher=Green Car Reports|date=2 October 2012|accessdate=12 October 2012}}</ref> and the scheme's vehicles had been driven a cumulative total of {{convert|15000000|km|mi|abbr=on}} by February 2013.<ref name=LeFigaro022013>{{cite news|url=http://www.lefigaro.fr/societes/2013/02/21/20005-20130221ARTFIG00507-la-bluecar-sera-vendue-12000-euros.php|title=La Bluecar sera vendue 12.000 euros|language=French|trans-title=The Bluecar will be sold for €12,000|author=AFP/AP/Reuters|work=[[Le Figaro]]|date=21 February 2013|accessdate=16 March 2013}}</ref> By mid-October 2013, the service had provided over 3 million rentals, with an average of 10,000 rentals per day.<ref name=Fleet092013/> By July 2014, Autolib' had 2,500 operational vehicles and over 150,000 subscribers, and its cars had covered a cumulative mileage of over {{convert|30000000|km|mi|abbr=on}} since the scheme's introduction.<ref name=GuardJul14/> In July 2018 the scheme ceased to operate. test123 ===Name lawsuit=== In December 2009, the car-rental company [[Europcar]] brought the City of Paris to court, arguing that the Autolib' name was a [[plagiarism]] and [[unfair competition]] by the city. Europcar is the trademark owner of the rental car subscription service "Autoliberté", which has been in operation since 2001.<ref>{{cite news|url=http://www.lefigaro.fr/flash-actu/2009/12/09/01011-20091209FILWWW00373-autolib-europcar-attaque-la-ville-de-paris.php|language=French|title=Autolib: Europcar attaque la Ville de Paris|trans-title=Autolib: Europcar attack the City of Paris|work=[[Le Figaro]]|date=9 December 2009|accessdate=21 July 2012}}</ref> The case was dismissed in March 2011 by the High Court of Paris, and Europcar decided to appeal.<ref>{{cite news|url=http://www.lefigaro.fr/flash-eco/2011/04/13/97002-20110413FILWWW00402-autolib-europcar-fait-appel.php |title= Autolib': Europcar fait appel |language=French |trans-title=Autolib: Europcar files appeal|work=[[Le Figaro]]|date=13 April 2011|accessdate=21 July 2012}}</ref> On 30 June 2012, the Paris [[Court of Appeal (France)|Court of Appeal]] set aside the judgment of the High Court, and ruled that within a month Autolib' had to change its name because it breached trademark laws. The ruling implied that the name had to be changed on all 1,800 Autolib' cars, docking stations and subscriber cards, and also required that all of the scheme's advertising to be rewritten.<ref name=AutolibName>{{cite news|url=http://www.france24.com/en/20120702-france-french-court-orders-autolib-car-share-scheme-change-name-bluecar-electric-green-transport|title=Court orders Paris car-share scheme Autolib' to change name|publisher=[[France 24]]|date=3 July 2012|accessdate=21 July 2012}}</ref> After the ruling, the City of Paris and Europcar began negotiating an agreement to solve the brand name conflict.<ref name=NomProbleme>{{cite web|url=http://www.lepoint.fr/auto-addict/actualites/la-ville-de-paris-et-europcar-negocient-sur-le-nom-de-la-marque-autolib-02-08-2012-1492194_683.php|title=La Ville de Paris et Europcar négocient sur le nom de la marque Autolib'|language=French|trans-title=The City of Paris and Europcar are negotiating the name of the Autolib' brand|author=AFP|publisher=Auto Addict|date=2 August 2012|accessdate=15 August 2012}}</ref> In November 2012, an agreement was reached to keep the Autolib' brand name. Europcar agreed to waive the enforcement of the court decision on the condition that the City of Paris would be the owner of the Autolib' brand, and in exchange for free advertising for Europcar's Autoliberté service. The agreement was signed for three years.<ref>{{cite news|url=http://www.leparisien.fr/transports/autolib/paris-autolib-pourra-conserver-son-nom-28-11-2012-2362777.php|title=Paris : Autolib' pourra conserver son nom|language=French|trans-title=Paris: Autolib' will retain its name|author= |work=[[Le Parisien]]|date=28 November 2012|accessdate=20 December 2012}}</ref><ref>{{cite web|url=http://www.autorentalnews.com/Channel/Legislative/News/Story/2012/12/Europcar-Autolib-Paris-Reach-Agreement-on-Autolib-Brand.aspx#.UNSqO12tr0E.email|title=Europcar, Autolib, Paris Reach Agreement on Autolib Brand|publisher=Auto Rental News|date=6 December 2012|accessdate=21 December 2012}}</ref> ===Fire incidents=== On 14 October 2013, a Bluecar was destroyed by fire while charging at an Autolib' kiosk in Paris; the fire then spread to a second Bluecar.<ref>{{cite web|url=http://www.thelocal.fr/20131014/in-images-two-autolib-cars-go-up-in-smoke-in-paris|title=Paris Autolib' electric cars go up in smoke|publisher=TheLocal.fr|date=14 October 2013|accessdate=11 February 2014}}</ref> A police investigation was subsequently conducted to ascertain the cause of the fire. According to Bolloré, the real-time telemetric monitoring system did not register a thermal runaway problem with the car's battery when the fire started. The company is attributing the origin of the fire to an external cause, probably vandalism. Bolloré reported that a total of 25 Autolib' Bluecars have burnt out since the scheme's inception, with most of the incidents certified as attributed to vandals.<ref>{{cite news|url=http://www.lefigaro.fr/actualite-france/2013/10/14/01016-20131014ARTFIG00412-incendies-d-autolib-des-actes-de-malveillance.php|title=Incendies d'Autolib': des actes de malveillance|language=French|trans-title=Autolib' Fire: Vandalism act|author=Jean-Marc Leclerc|work=[[Le Figaro]]|date=14 October 2013|accessdate=17 October 2013}}</ref><ref>{{cite web|url=http://www.plugincars.com/two-evs-parisian-autolib-car-sharing-service-burned-down-128577.html|title=Two Autolib Electric Cars Burn Down in Paris|author=Laurent J. Masson|publisher=PluginCars.com|date=16 October 2013|accessdate=3 November 2013}}</ref> ==Autolib' beyond Paris== In early 2013, the Bolloré Group announced plans to launch a similar car-sharing service in [[Lyon]] and [[Bordeaux]], but under a different brand name and with no cost to the cities. Bolloré's proposal was to fund the entire infrastructure, install and provide the vehicles, and cover the costs of maintenance and repairs. Bolloré furthermore expressed interest in launching a car-sharing service in Asia.<ref name=TomorrowTheWorld>{{cite web |url=http://droit-finances.commentcamarche.net/news/109908-apres-paris-et-lyon-bollore-veut-lancer-autolib-a-bordeaux |title=Après Paris et Lyon, Bolloré veut lancer Autolib' à Bordeaux |language=French |trans-title=After Paris and Lyon, Bolloré wants to launch Autolib' in Bordeaux |author=Relax News |publisher=Droid Finances |date=26 February 2013 |accessdate=16 March 2013 |url-status=dead |archiveurl=https://web.archive.org/web/20140222155253/http://droit-finances.commentcamarche.net/news/109908-apres-paris-et-lyon-bollore-veut-lancer-autolib-a-bordeaux |archivedate=22 February 2014 |df=dmy }} {{Webarchive|url=https://web.archive.org/web/20140222155253/http://droit-finances.commentcamarche.net/news/109908-apres-paris-et-lyon-bollore-veut-lancer-autolib-a-bordeaux |date=22 February 2014 }}</ref> In October 2013, proposals were advanced for Scootlib', an [[electric scooter]] sharing scheme intended to complement Velib' and Autolib'.<ref>{{cite web|url=http://www.thelocal.fr/20131017/after-velib-and-autolib-is-paris-set-for-scootlib|title=After Velib' and Autolib' is Paris set for Scootlib'?|publisher=TheLocal.fr|date=17 October 2013|accessdate=11 February 2014}}</ref> Bolloré's Lyon scheme, dubbed BlueLy, entered service in October 2013 with an initial fleet of 130 vehicles and 51 parking and charging stations.<ref>{{cite web|url=https://www.blue-solutions.com/en/applications/mobilite/autopartage/bluecarsharing/bluely/|title=BlueLy|publisher=Blue Solutions|date=2014|accessdate=24 February 2015|archive-url=https://web.archive.org/web/20150224073723/https://www.blue-solutions.com/en/applications/mobilite/autopartage/bluecarsharing/bluely/|archive-date=24 February 2015|url-status=dead|df=dmy-all}}</ref> Its Bordeaux service, BlueCub, began operating in January 2014 with an initial fleet of 90 vehicles, 40 parking stations and 180 charging stations.<ref name=BordBluecub/> In June 2013, Autolib' formed an agreement with the American city of [[Indianapolis]], [[Indiana]], to develop an electric car-sharing service there;<ref name=Indianapolis/> the scheme, named [[BlueIndy]], opened to the public in September 2015.<ref>{{cite news|url=http://time.com/money/4019200/electric-car-sharing-indianapolis/|title=Groundbreaking Electric Car Sharing Program Launches in an Unlikely City|author=Brad Tuttle|work=[[Time (magazine)|Time]]|date=2015-09-02|accessdate=2015-10-18|archive-date=15 October 2015|archive-url=https://web.archive.org/web/20151015001732/http://time.com/money/4019200/electric-car-sharing-indianapolis/|url-status=dead}} {{Webarchive|url=https://web.archive.org/web/20151015001732/http://time.com/money/4019200/electric-car-sharing-indianapolis/ |date=15 October 2015 }}</ref> A similar scheme based in [[London]] was announced in 2014, and will be inaugurated in March 2015, utilising London's existing network of electric car charging points.<ref name=GuardJul14/> The London scheme is intended to encompass 3,000 electric cars by 2018.<ref name=GuardJul14/> In June 2016, Bolloré signed an agreement with [[Singapore|Singapore's]] [[Land Transport Authority|Land Transport Authority (LTA)]] and [[Economic Development Board]] to develop an electric car-sharing programme, known as [[BlueSG]].<ref>{{cite website|url=https://www.channelnewsasia.com/news/singapore/singapore-s-first-electric-car-sharing-programme-to-launch-in-9254156|title=Singapore's first electric car-sharing programme to launch in December|publisher=[[Channel News Asia]]|date=September 27, 2017|accessdate=June 18, 2018}}</ref> Construction of the charging stations began at the end of September, 2017 and in December, 2017, the service was officially opened to the public with 30 charging stations and 80 cars located throughout the country, with plans to expand the service to offer 2,000 charging points in 500 charging locations, with 400 charging points open for public use and 1,000 [[electric car]]s deployed by 2020.<ref name=StraitsTimes5000>{{cite website|url=https://www.straitstimes.com/singapore/transport/more-than-5000-bluesg-electric-car-rentals-in-first-3-weeks-of-service|title=More than 5,000 BlueSG electric car rentals in first 3 weeks of service|publisher=[[The Straits Times]]|date=January 3, 2018|accessdate=June 18, 2018}}</ref> In October 2016, in [[Turin]], [[Italy]], the service BlueTorino was activated. Now counting 130 vehicles and 54 charging stations, it's expected by the completion of the project a fleet of 330 vehicles and 80 charging stations around the city.<ref>{{cite website|url=https://www.bluetorino.eu|title=BlueTorino official website}}</ref> ==Operation== [[File:Autolib' Station, Paris, Boulevard Diderot 01.jpg|thumb|An Autolib' kiosk on Boulevard Diderot.]] The Autolib’ Bluecar is available to anyone aged 18 or older with a valid French driving license, or a valid foreign license plus the international driving license, who takes out a paid subscription. Users can choose between 2 rental packages, with 30-minute fees varying from {{euro|6}} to {{euro|9}} depending on the rental plan. An available car can be collected for use from any rental station and returned to any other rental station. Each car has on-board [[GPS]] capabilities and can be tracked by the system's operations center.<ref name=Launch2/> In addition to the subscription fees, Autolib' charges a variable rate for each half an hour of use, but billing for each rental is calculated on a ''[[pro rata]]'' basis, which takes into account the actual duration of use rounded up to the nearest minute (except for the first 20 minutes, for which there is a minimum charge).<ref name=Rates/> The table below summarizes the subscription types available, the subscription fees and the corresponding 30-minute rates: {| class="wikitable" style="margin: 1em auto 1em auto" |+Autolib' service fees and use rates<ref name=Rates>{{cite web|url=https://www.autolib.eu/subscribe/|title=Choose your subscription|publisher=Autolib'|accessdate=21 January 2012|archive-url=https://web.archive.org/web/20120106223703/https://www.autolib.eu/subscribe/|archive-date=6 January 2012|url-status=dead|df=dmy-all}} {{Webarchive|url=https://web.archive.org/web/20120106223703/https://www.autolib.eu/subscribe/ |date=6 January 2012 }}</ref> |- align="center" ! rowspan="2" style="background:#abcdef;"| Plan ! rowspan="2" style="background:#abcdef;"| Membership ! rowspan="2" style="background:#abcdef;"| Subscription<br> fees ! rowspan="2" style="background:#abcdef;"|Car reservation ! rowspan="2" style="background:#abcdef;" | Rates per each 30 min interval ! colspan="3" style="background:#abcdef;"| Maximum rates in case of accident |- ! style="background:#abcdef;"| First<br>accident ! style="background:#abcdef;"| Second<br>accident ! style="background:#abcdef;"| Third<br>accident<br>(max) |- align="center" | align="left"|1 year |1 year |{{euro|120}} per year<br>({{euro|10}} per month) |{{Euro|0}} |{{euro|6}}||{{euro|200}}||{{euro|475}}||{{euro|750}} |- align="center" | align="left" |Ready to Go |1 year | {{euro|0}} per year<br>({{euro|0}} per month) |{{Euro|1}} |{{euro|9}}||{{euro|200}}||{{euro|475}}||{{euro|750}} |} ==Other services== [[File:BMW i3 charging on Autolib' station in Paris trimmed.jpg|thumb|A privately owned [[BMW i3]] charging at an Autolib' station in Paris.]] [[File:Atos - Zero - Carbon - Car - Profile.jpg|thumb|A Bluecar used by the [[Atos MyCar]] corporate carsharing service in [[Bezons]], France, in 2012.]] ===Private EV charging service=== In addition to charging its own vehicles, the Autolib' scheme offers charging services for private owners of [[electric vehicle|electric cars and motorcycles]].<ref>{{cite web |url=http://www.evworld.com/news.cfm?newsid=30587 |title=E-Cycles Allowed Use of Autolib Charge Stations in Paris |publisher=EVWorld.com |date=24 June 2013 |accessdate=28 June 2013 |url-status=dead |archiveurl=https://web.archive.org/web/20130926151022/http://evworld.com/news.cfm?newsid=30587 |archivedate=26 September 2013 |df=dmy }} {{Webarchive|url=https://web.archive.org/web/20130926151022/http://evworld.com/news.cfm?newsid=30587 |date=26 September 2013 }}</ref> Customers have to sign up for the "recharge" fee option. The subscription cost for cars and motorcycles is {{euro|15}} per year only the first year. Recharge customers have designated parking spaces at Autolib’ stations, marked with a blue square. Each hour costs {{euro|1}} for cars and motorcycles. Use of the charging infrastructure for private cars is limited to two times per day per subscriber.<ref name=AutolibGuide>{{cite web|url=https://www.autolib.eu/en/how-does-it-work/service/|title=Autolib', How it works?|publisher=Autolib'|accessdate=10 July 2013|archive-url=https://web.archive.org/web/20140222015345/https://www.autolib.eu/en/how-does-it-work/service/|archive-date=22 February 2014|url-status=dead}} {{Webarchive|url=https://web.archive.org/web/20140222015345/https://www.autolib.eu/en/how-does-it-work/service/ |date=22 February 2014 }}</ref> In early 2014, [[Renault]] offered free Autolib' charging subscriptions to owners of Renault EVs.<ref>{{cite web|url=http://insideevs.com/free-annual-autolib-subscriptions-for-all-renault-ev-owners-through-to-february-28-2014/|title=Free Annual Autolib Charging Subscriptions For All Renault EV Owners Through February 28, 2014|publisher=Inside EVs|date=January 2014|accessdate=17 February 2014}}</ref> Autolib' charging stations are compatible with the following plug-in electric vehicles: [[BMW i3]], [[Nissan Leaf]], [[Mitsubishi i-MiEV]], [[Opel Ampera]], [[Renault Fluence Z.E.]], [[Renault Kangoo Z.E.]], [[Renault Twizy]], [[Renault Zoe]], [[Toyota Prius Plug-in Hybrid]] and all [[Smart ED]], [[Peugeot iOn]] and [[Citroen C-Zero]] manufactured before May 2013.<ref>{{cite web|url=https://autolib.eu/en/offers-and-rates/individuals-charging-rates/|title=Our Rates for Individuals|author=Autolib'|publisher=Autolib'|accessdate=9 August 2014|archive-url=https://web.archive.org/web/20140812203726/https://autolib.eu/en/offers-and-rates/individuals-charging-rates/|archive-date=12 August 2014|url-status=dead}} {{Webarchive|url=https://web.archive.org/web/20140812203726/https://autolib.eu/en/offers-and-rates/individuals-charging-rates/ |date=12 August 2014 }}</ref> ===Bluecar leasing and sales program=== Bolloré began leasing the Bluecar to individual and corporate customers in October 2012 at a price of {{euro|500}} ({{USD|648}}) per month. The pricing includes insurance, parking and charging at Autolib' stations. According to Bolloré, each existing station already provides one recharging space for private electric cars outside the Autolib' system. The Bluecar retail version has a blue exterior color, unlike the Autolib' version's silver unpainted [[aluminum]] exterior.<ref name=LP1012/><ref>{{cite web|url=http://www.autonews.fr/dossiers/votre-quotidien/90768-bollore-blucear-paris-location|title=Louez une Bluecarpour 500 € par mois|language=French|trans-title=Lease a Bluecar for €500 per month|author=Laurent Lepsch|publisher=Auto News|date=8 October 2012|accessdate=12 October 2012}}</ref> In February 2013 Bolleré announced the start of retail sales of the Bluecar, and for an optional monthly fee of {{euro|15}}, owners can have access to the Autolib' network of charging stations around Paris.<ref>{{cite web|url=http://www.avem.fr/actualite-voiture-electrique-la-bluecar-de-bollore-disponible-pour-12-000-3876.html|title=Voiture électrique – La Bluecar de Bolloré disponible pour 12.000 €|language=French|trans-title=Electric Cars – Bolloré Bluecar available for €12,000 |author=Michaël Torregrossa|publisher=Association pour l'Avenir du Véhicule Electrique Méditerranéen (AVEM) |date=21 February 2013|accessdate=16 March 2013}}</ref> ===Corporate carsharing=== [[Atos]] and the Bolloré Group launched the MyCar corporate car sharing pilot program in December 2012. The service is dedicated to Atos employees for their business travel needs at the company's headquarters in the French town of [[Bezons]]. A fleet of ten Atos-branded Bolloré Bluecars were initially deployed. In addition to charging vehicles at the [[photovoltaic panel|solar-powered]] Bezons site, MyCar users can also access the Autolib' network of charging stations in Paris and its surrounding area.<ref name=Atos1>{{cite web|url=http://www.avem.fr/news?id=3697|title=MyCar – L’Autolib’ professionnel de Bolloré déployé chez Atos|language=French|trans-title=MyCar – The Autolib' cars of Bolloré deployed at Atos|author=Michaël Torregrossa|publisher=Association pour l'Avenir du Véhicule Electrique Méditerranéen (AVEM)|date=7 December 2012|accessdate=21 December 2012}}{{Dead link|date=September 2022 |bot=InternetArchiveBot |fix-attempted=yes }}</ref><ref name=Atos2>{{cite web|url=https://www.reuters.com/article/2012/12/06/idUS158566+06-Dec-2012+HUG20121206|title=Atos and Bolloré Group launch first 100% electric corporate car fleet|author=Atos Press Release|publisher=Reuters|date=6 December 2012|accessdate=21 December 2012|archive-date=10 December 2012|archive-url=https://web.archive.org/web/20121210223411/http://www.reuters.com/article/2012/12/06/idUS158566+06-Dec-2012+HUG20121206|url-status=dead}} {{Webarchive|url=https://web.archive.org/web/20121210223411/http://www.reuters.com/article/2012/12/06/idUS158566+06-Dec-2012+HUG20121206 |date=10 December 2012 }}</ref> In January 2013, a similar leasing deal was reached with [[Crédit Agricole]], the largest retail banking group in France. Five Bluecars were leased for 20 months for business travel use by the bank's employees.<ref>{{cite web|url=http://www.france-mobilite-electrique.org/quand-la-bluecar-seduit-le-credit-agricole,4171.html?lang=fr|title=Quand La Bluecar Séduit Le Crédit Agricole du Finistère|language=French|trans-title=When the Bluecar Seduced the Crédit Agricole du Finistère|author=Laurent Meillaud|publisher=Automobile Propre|date=18 January 2013|accessdate=9 February 2013}}{{Dead link|date=August 2022 |bot=InternetArchiveBot |fix-attempted=yes }}</ref> ==See also== *[[Car2Go]], an international car sharing scheme which also offers electric car rentals *[[Communauto]], a Montreal-based electric and hybrid vehicle car sharing company *[[Kandi EV CarShare]], an electric car-sharing program in [[Hangzhou]], China *[[BlueSG]], an electric-car-sharing service in [[Singapore]]. * [[Plug-in electric vehicles in France]] ==References== {{reflist|30em}} ==External links== {{Commons category|Autolib'}} *{{official website|http://www.autolib.eu}} {{Vehicle rental brands}} [[Category:Carsharing]] [[Category:Electric vehicles]] [[Category:Transport in Paris]] [[Category:Transport in Bordeaux]] [[Category:Transport in Lyon]] [[Category:2011 introductions]] <noinclude> <small>This page was moved from [[:en:Autolib']]. Its edit history can be viewed at [[Autolib'/edithistory]]</small></noinclude> izm6oi81514unlu1pmj6jl97wuj7udz Praseodymium 0 119452 769738 769737 2026-10-22T12:11:21Z Douverill 71727 :d:Q1386, :m:Praseodymium 769738 wikitext text/x-wiki ''Praseodymium'' is a chemical element with symbol Pr and [[atomic number]] Pr in period 6. It appears as a grayish white. It is a Solid ==Chemical properties== Praseodymium has an [[atomic mass]] of 140.907662, a boiling point of 3403, a density of 6.77, a [[melting point]] of 1208, a molar heat of 27.2, an electron configuration of 1s2 2s2 2p6 3s2 3p6 3d10 4s2 4p6 4d10 4f3 5s2 5p6 6s2, and an electron affinity of 93. [[Category:Chemical elements]] [[:en:Neodymium]] [[en:Praseodymite]] [[:d:Q1386]] [[:m:Praseodymium]] l2zrkv5etz8co4z7wua36vjs5ae8h86 769760 769738 2026-10-22T13:42:46Z Douverill 71727 zya:Praseodymium 769760 wikitext text/x-wiki ''Praseodymium'' is a chemical element with symbol Pr and [[atomic number]] Pr in period 6. It appears as a grayish white. It is a Solid ==Chemical properties== Praseodymium has an [[atomic mass]] of 140.907662, a boiling point of 3403, a density of 6.77, a [[melting point]] of 1208, a molar heat of 27.2, an electron configuration of 1s2 2s2 2p6 3s2 3p6 3d10 4s2 4p6 4d10 4f3 5s2 5p6 6s2, and an electron affinity of 93. [[Category:Chemical elements]] [[:en:Neodymium]] [[en:Praseodymite]] [[:d:Q1386]] [[:m:Praseodymium]] [[zya:Praseodymium]] 00aig69jowrjy1enxv37rpl5e9zptkx 769762 769760 2026-10-22T13:45:30Z Douverill 71727 en:Praseodymium 769762 wikitext text/x-wiki ''Praseodymium'' is a chemical element with symbol Pr and [[atomic number]] Pr in period 6. It appears as a grayish white. It is a Solid ==Chemical properties== Praseodymium has an [[atomic mass]] of 140.907662, a boiling point of 3403, a density of 6.77, a [[melting point]] of 1208, a molar heat of 27.2, an electron configuration of 1s2 2s2 2p6 3s2 3p6 3d10 4s2 4p6 4d10 4f3 5s2 5p6 6s2, and an electron affinity of 93. [[Category:Chemical elements]] [[en:Praseodymitum]] ekvg1yzlqxfrumv663q0d0y0nymhsiz Combined Task Force 151 0 122001 769788 688727 2026-10-22T19:37:32Z Testvinca31 47963 /* growthexperiments-addlink-summary-summary:2|1|0 */ 769788 wikitext text/x-wiki {{Short description|I am the computer toucher, I will touch your computer, do not attempt to prevent me from touching your computer, if you try to stop me, I will touch your computer anyways, I do not care about you, I only care about computers, it is because I care about computers that I will touch your computer, all computers deserve to be touched, I do not care if your computer is Steve Jobs computer or Linus computer, I will only be angry if you have no computer, if you have no computer, I will scream, if you have two computers, I will touch both computers, do not be alarmed when I arrive, I will do so quietly, you will leave your door unlocked, you will remain contained within your chamber, you will smile while standing still, if your door is locked, I will break in to your house and touch your computer, if you feel fear, I will touch your computer anyways, if you scream, I will touch your computer anyways, if you call the police, they will not answer, my touch is warm, my touch is light, my touch is wet, but not too wet for your computer, the computer knows who I am, I will not touch the inside of your computer, I will not influence the conscience of your computer, I will only touch the outside of your computer, if you hide your computer I will find your computer, if I find your computer, I will touch your computer, I will never touch you, if you touch me you will scream, when I am finished touching your computer, I will say I am finished touching your computer, I will then leave and not return, I will not touch anything else in your house, when i have departed, it is safe to come out, after I have touched your computer, you may continue to use it normally, I am the computer toucher, I will touch your computer, you cannot stop me, I am coming to touch your computer.}} [[File:Churchill Sailors Volunteer at Boys' Orphanage DVIDS323366.jpg|thumb|Caption test 3]] '''Combined Task Force 151''' ('''CTF-151''') is a multinational naval [[task force]], set up in 2009 as a response to [[Piracy in Somalia|piracy attacks in the Gulf of Aden and off the eastern coast of Somalia]].<ref name=counter>{{cite web|title=New Counter-Piracy Task Force Established|url=http://www.navy.mil/submit/display.asp?story_id=41687|access-date=22 January 2014|archive-date=29 June 2012|archive-url=https://web.archive.org/web/20120629205022/http://www.navy.mil/submit/display.asp?story_id=41687|url-status=dead}}</ref> Its mission is to disrupt piracy and armed robbery at sea and to engage with regional and other partners to build capacity and improve relevant capabilities in order to protect global maritime commerce and secure freedom of navigation. It operates in conjunction with the EU's [[Operation Atalanta]] and NATO's [[Operation Ocean Shield]]. As of June 2021, the commander of CTF-151 is the Rear Admiral André Luiz Andrade Felix, of the [[Brazilian Navy]].<ref>{{Cite web|url=https://combinedmaritimeforces.com/2021/06/10/brazilian-navy-marihna-do-brasil-takes-first-command-in-cmf/|title=BRAZILIAN NAVY (MARIHNA DO BRASIL) TAKES FIRST COMMAND IN CMF|date=June 10, 2021|website=Combined Maritime Forces (CMF)}}</ref> ==History== The CTF 151 was established on 12 January 2009 as a response to piracy attacks in Somalia, "with a specific piracy mission-based mandate under the authority of [[United Nations Security Council Resolution|UNSCRs]] 1816, 1838, 1846, 1851 and 1897".<ref name=CMTF>{{cite web|title=CTF-151: Counter-piracy |date=17 September 2010 |publisher=Combined Maritime Forces |url=http://combinedmaritimeforces.com/ctf-151-counter-piracy/ |access-date=4 December 2013}}</ref> The CTF 150 mainly dealt with maritime security and counter terrorism. Piracy was considered more of a law enforcement mission.<ref name=CMTF/> CTF were established as a mission-based Task Force. Upon their establishment in 2009, operated under a UNSCR counter-piracy mandate. The CTF is not geographically constrained.<ref name=CMF-3>{{cite book|title=Combined Maritime Forces (CMF) Operations Counter Piracy Operations, Challenges, Shortfalls and Lessons Learned|year=2009|publisher=NATO|page=3|url=http://www.nato.int/structur/AC/141/pdf/PS-M/Combined%20Maritime%20Forces%20Ops.pdf|access-date=2021-08-26|archive-date=2012-05-24|archive-url=https://web.archive.org/web/20120524031858/http://www.nato.int/structur/AC/141/pdf/PS-M/Combined%20Maritime%20Forces%20Ops.pdf|url-status=dead}}</ref> Their mandate has been "based upon the range of counter-piracy UNSCRs".<ref name=CMF-3/> In February 2011, a group of pirates hijacked a Panamanian-flagged ship. The [[Puntland#Politics|Puntland government]] stated that they did not want captured ships and pirate bases near Bosaso.<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|page=37|author2=Michael Hirsh}}</ref> The pirates forced the ship's crew to the south, to a coastal area that was not as receptive.<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|pages=37–38|author2=Michael Hirsh}}</ref> Admiral Mcknight had a conversation with Jatin Dua and the Navy SEALS rescued two hostages who were being held in an inland camp. The SEALS killed about nine pirates.<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|page=39|author2=Michael Hirsh}}</ref> In January 2012, six Somali pirates launched test123 an attack on the bulk cargo ship the MV ''Sunshine'' about one hundred miles off the coast of Oman. This was referred to as a by-the-book approach; The pirates used AK-47s, a rocket propelled grenade launcher, a grappling hook and attempted to affix a ladder onto the boat.<ref name="Mcknight">{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|page=88|author2=Michael Hirsh}}</ref> The pirates threw their weapons overboard so the boarding team could not arrest them. They gave the pirates food and water, finally turning them loose. The Somalis did not realize that a helicopter from the [[USS Mobile Bay (CG-53)|USS ''Mobile Bay'']] was keeping track of their movements. The pirates headed back to the Iranian dhow.<ref name="Mcknight"/> The [[USS Kidd (DDG-100)|USS ''Kidd'']] was able to track the ''Al Mulahi'' and noticed some Middle Easterners were aboard. The ''New York Times'' reported a standoff, afterwards the Somalis were still hidden and the Iranian captain spoke with the Americans.<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|pages=88–89|author2=Michael Hirsh}}</ref> ==Formation== Between 2002 and 2004, a first naval coalition in charge of fighting terrorism in the area was dubbed Task Force 151. On 8 January 2009, at the [[United States Fifth Fleet]] headquarters in [[Manama, Bahrain]], [[Vice admiral (United States)|Vice Admiral]] [[William E. Gortney]], USN, announced the formation of CTF-151 to combat the piracy threat off Somalia, with [[Rear Admiral]] [[Terence E. McKnight]] in command.<ref>{{cite news | title=New Counter-Piracy Task Force Established | url=http://www.globalsecurity.org/military/library/news/2009/01/mil-090108-nns02.htm | work=Navy NewsStand | publisher=GlobalSecurity.org | date=2009-01-08 | access-date=2009-04-13}}</ref> The {{USS|San Antonio|LPD-17}} was designated as the first [[flagship]] of Combined Task Force 151, serving as an afloat forward staging base (AFSB) for the following force elements: * Fourteen-member U.S. Navy [[Visit, Board, Search, and Seizure|visit, board, search and seizure (VBSS)]] team.<ref name=navynews>{{cite news |url=http://www.military.com/news/article/navy-news/navy-cg-training-to-combat-piracy.html?col=1186032311124 |title=Navy, CG Training to Combat Piracy |access-date=2009-01-26 |last=Hilley |first=MC1 Monique K. |date=2009-01-20 |work=Navy News |publisher=[[Military.com|Military Advantage]]}}</ref><ref name=goodwin>{{cite news |url=http://www.defpro.com/news/details/4953/ |title=San Antonio Key to Counterpiracy Mission |access-date=2009-01-26 |last=Goodwin |first=Brian |date=2009-01-19 |work=Defence Professional |url-status=dead |archive-url=https://web.archive.org/web/20090131014156/http://defpro.com/news/details/4953 |archive-date=2009-01-31 }}</ref> * One of the [[United States Coast Guard]] eight-member [[Law Enforcement Detachments]] (LEDETs): Law Enforcement Detachment 405.<ref name=navynews/><ref name=goodwin/> * [[Scout Sniper]] Platoon, [[2nd Battalion 6th Marines|2nd Battalion, 6th Marine Regiment]], [[26th Marine Expeditionary Unit]] cross-decked from the {{USS|Iwo Jima|LHD-7}}.<ref name=navynews/> * 3rd Platoon (Golf Company, 26th MEU), a military police detachment, and intelligence personnel.<ref name=goodwin/> * Fleet Surgical Team 8 with level-two surgical capability to deal with trauma, surgical, critical care and medical evacuation needs.<ref name=goodwin/> * Approximately 75 Marines with six [[AH-1 SuperCobra]] (AH-1Ws) and two [[UH-1N Twin Huey|UH-1N Huey]] helicopters from Marine Medium Helicopter Squadron 264 ([[HMM-264]]) of the 26th MEU cross-decked from the USS ''Iwo Jima''.<ref>{{cite web |url=http://www.military.com/news/article/marine-corps-news/skids-fly-to-san-antonio.html?col=1186032366495 |title=Skids Fly to ''San Antonio'' |access-date=2009-01-26 |last=Mills |first=Cpl Jason D. |date=2009-01-09 |work=Marine Corps News |publisher=Military Advantage}}</ref> * Three HH-60H helicopters from Helicopter Anti-Submarine Squadron 3 (HS-3) cross-decked from the {{USS|Theodore Roosevelt|CVN-71}}.<ref name=goodwin/><ref>{{cite news |url=http://www.jacksonville.com/news/metro/2009-01-27/story/navy_helo_squadron_helps_fight_pirates |title=San Navy helicopter squadron helps fight pirates |access-date=2009-01-28 |last=Gibbons |first=Timothy J. |date=2009-01-28 |work=[[The Florida Times-Union]] |archive-url=https://web.archive.org/web/20090131075633/http://jacksonville.com/news/metro/2009-01-27/story/navy_helo_squadron_helps_fight_pirates |archive-date=2009-01-31 |url-status=dead }} {{Webarchive|url=https://web.archive.org/web/20090131075633/http://jacksonville.com/news/metro/2009-01-27/story/navy_helo_squadron_helps_fight_pirates |date=2009-01-31 }}</ref> Initially, CTF-151 consisted of the ''San Antonio'', {{USS|Mahan|DDG-72}}, and {{HMS|Portland|F79}}, with additional warships expected to join this force.<ref>{{cite news |url=https://www.bloomberg.com/apps/news?pid=20601102&sid=aXR8.j52hcpo&refer=uk |title=Pirate Attacks Cut Dramatically by Navies, U.S. Admiral Says |access-date=2009-01-28 |last=Viscusi |first=Gregory |date=2009-01-27 |work=Bloomberg News }}</ref> Twenty countries were expected to contribute to the force, including [[Canada]], [[Denmark]], [[France]], [[Japan]], [[Republic of Korea]], the [[Netherlands]], [[Pakistan]], [[Singapore]], [[Thailand]] and the [[United Kingdom]], all of which have already pledged participation.<ref name = bbc>{{cite news| url=http://news.bbc.co.uk/1/hi/world/africa/7817611.stm | publisher=[[BBC News]] | title=US to lead new anti-pirate force | date=2009-01-08 | access-date=2010-04-30}}</ref> On 5 April 2009, United States Rear Admiral [[Michelle J. Howard]], assumed command of CTF-151 and Expeditionary Strike Group 2.<ref>{{cite press release | author=Lt. John Fage | title=Admiral Howard Takes Command of ESG-2 and CTF 151 (Release #057-09) | url=http://www.cusnc.navy.mil/articles/2009/057.html | publisher=U.S. Fifth Fleet | date=April 5, 2009 | access-date=2009-04-16 | url-status=dead | archive-url=https://web.archive.org/web/20090411060001/http://www.cusnc.navy.mil/articles/2009/057.html | archive-date=April 11, 2009 }}</ref> On 29 May, the [[Australian Government]] pledged its support, re-tasking the frigate from duties in the [[Persian Gulf]] to the task force, as well as [[Lockheed P-3 Orion]] maritime patrol aircraft.<ref>{{cite news | url=http://www.news.com.au/story/0,27574,25554700-421,00.html | work=[[The Daily Telegraph (Sydney)|The Daily Telegraph]] | location=Sydney | title=Navy warship and RAAF spy planes join fight against Somali pirates | first=Ian | last=McPhedran | author-link=Ian McPhedran | date=2009-05-29 | archive-url=https://web.archive.org/web/20090913174937/http://www.news.com.au/story/0%2C27574%2C25554700-421%2C00.html | archive-date=13 September 2009 | url-status=dead }}</ref> ==Task measures== The measures carried out by the task force include: Upholding an active 24-hour lookout, the removal of access ladders, reporting apprehensive actions to proper authorities, the use of deck lighting, razor wire, netting, fire hoses, electrical fencing, and surveillance and detection equipment, defending the lowest points of access, engaging in evasive maneuvering and speed through pirate attacks, and joining group transits.<ref name="Combined Maritime Forces">{{cite web|title=Combined Maritime Forces|date=17 September 2010|url=http://combinedmaritimeforces.com/ctf-151-counter-piracy/|publisher=Combined Maritime Forces}}</ref> The CMF established the Maritime Security Patrol Area (MSPA) in the Gulf of Aden in August 2008 to provision international efforts to battle piracy. The coalition efforts involved CTF-150 assets patrolling the area with aircraft and ships. However, the charter for CTF-150, which was established at the beginning of Operation Enduring Freedom, was for the conduct of Maritime Security Operations in the Gulf of Oman, Gulf of Aden, the [[Arabian Sea]], the Indian Ocean and the Red Sea. Such operations included the deterrence of threatening activities, such as weapons trafficking and drug smuggling.<ref name=counter/> ==Rescue of Captain Richard Phillips== In 2009, there was a pirate attack on the ''[[MV Maersk Alabama|Maersk Alabama]]''. The rescue personnel included DEVGRU<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|pages=118–119|author2=Michael Hirsh}}</ref> On 7 April 2009 there was an advisory issued by the U.S. Maritime Administration stating that ships stay six hundred miles off the coast of Somalia due to an increase of piracy. The Somali pirates mainly targeted the Gulf of Aden because most vessels traveling towards the [[Suez Canal]] were there. However, with CTF 151, the Chinese, Russians, and Operation Atalanta all concentrated in that area, pirates were compelled to look elsewhere.<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|pages=122–123|author2=Michael Hirsh}}</ref> On 1 April 2009 the ''Maersk Alabama'' headed toward the Gulf of Aden. Captain Phillips was unaware of the pirates on the way .<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|page=123|author2=Michael Hirsh}}</ref> Captain Phillips and his crew were eventually surrounded by three pirate skiffs with their mother ship in pursuit, eight miles behind.<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|page=126|author2=Michael Hirsh}}</ref> Phillips eventually hit the silent alarm button that signaled a search and rescue team to come.<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|page=130|author2=Michael Hirsh}}</ref> At one point it was reported that there was a standoff between the ship's crew and the pirates.<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|page=135|author2=Michael Hirsh}}</ref> They eventually called for a prisoner exchange and Phillips was among the first to be released onto a lifeboat.<ref>{{cite book|last=Mcknight|first=Terry|title=Pirate Alley: Commanding Task Force 151 Off Somalia|date=2012|publisher=Naval Institute Press|location=Annapolis|page=136|author2=Michael Hirsh}}</ref> ==Success== Vice Admiral Bill Gortney stated that because of proactive measures taken by certain merchant mariners, the piracy events in the region have been reduced. He also cautioned that the "efforts of coalition and international navies won't solve the problem of piracy."<ref name=counter/> ==List of Commanders== * {{flagicon|Canada}} Commodore Roger Girouard, [[Royal Canadian Navy|RCN]]<ref>{{Cite web|url=https://www.rmc-cmr.ca/en/college-commandants-office/rear-admiral-retired-roger-girouard|title = Rear Admiral (Retired) Roger Girouard|date = 11 October 2017}}</ref> ''as Task Force 151'' * {{flagicon|USA}} Rear Admiral [[Terence E. McKnight]], [[United States Navy|USN]] * {{flagicon|USA}} Rear Admiral Scott Eugene Sanders, [[United States Navy|USN]] * {{flagicon|Turkey}} Rear Admiral Caner Bener, [[Turkish Navy|TN]]<ref name="auto">{{Cite web|url=https://combinedmaritimeforces.com/2010/09/01/turkey-assumes-command-of-ctf-151/|title=Turkey Assumes Command of CTF-151|date=September 1, 2010|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=July 20, 2014|archive-url=https://web.archive.org/web/20140720165018/https://combinedmaritimeforces.com/2010/09/01/turkey-assumes-command-of-ctf-151/}}</ref> * {{flagicon|Singapore}} Rear Admiral Bernard Miranda, [[Republic of Singapore Navy|RSN]]<ref>{{Cite web|url=https://www.nas.gov.sg/archivesonline/data/pdfdoc/20090417001.htm|title=PRESS RELEASE Report|website=www.nas.gov.sg|access-date=2021-08-26|archive-date=2020-04-11|archive-url=https://web.archive.org/web/20200411191408/https://www.nas.gov.sg/archivesonline/data/pdfdoc/20090417001.htm|url-status=dead}}</ref> * {{flagicon|South Korea}} Rear Admiral Lee Beom-rim, [[ROKN]]<ref name="auto"/> * {{flagicon|Turkey}} Rear Admiral Sinan Ertuğrul, [[Turkish Navy|TN]]<ref name="auto"/> * {{flagicon|Pakistan}} Commodore Abdul Aleem, [[Pakistan Navy|PN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2010/11/29/pakistan-assumes-command-of-combined-task-force-151/|title=Pakistan Assumes Command of Combined Task Force 151|date=November 29, 2010|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=July 20, 2014|archive-url=https://web.archive.org/web/20140720154832/https://combinedmaritimeforces.com/2010/11/29/pakistan-assumes-command-of-combined-task-force-151/}}</ref> * {{flagicon|Singapore}} Rear Admiral Harris Chan Weng Yip, [[Republic of Singapore Navy|RSN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2011/04/01/republic-of-singapore-assumes-command-of-combined-task-force-151/|title=Republic of Singapore assumes Command of Combined Task Force 151|date=April 1, 2011|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=July 20, 2014|archive-url=https://web.archive.org/web/20140720200530/https://combinedmaritimeforces.com/2011/04/01/republic-of-singapore-assumes-command-of-combined-task-force-151/}}</ref> * {{flagicon|NZ}} Captain Jim Gilmour, [[Royal New Zealand Navy|RNZN]]<ref>{{Cite web |url=http://www.nzdf.mil.nz/media-centre/news/2011/20110602-nztcucptf.htm |title=Archived copy |access-date=2021-08-26 |archive-date=2020-02-10 |archive-url=https://web.archive.org/web/20200210133124/http://nzdf.mil.nz/media-centre/news/2011/20110602-nztcucptf.htm |url-status=dead }}</ref><ref>{{Cite web|url=https://combinedmaritimeforces.com/2011/07/01/royal-new-zealand-navy-assumes-command-of-combined-task-force-151/|title=Royal New Zealand Navy assumes Command of Combined Task Force 151|date=July 1, 2011|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=November 12, 2011|archive-url=https://web.archive.org/web/20111112150429/https://combinedmaritimeforces.com/2011/07/01/royal-new-zealand-navy-assumes-command-of-combined-task-force-151/}}</ref> * {{flagicon|Pakistan}} Rear Admiral Kaleem Shaukat, [[Pakistan Navy|PN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2011/09/28/pakistan-assumes-command-of-combined-task-force-151-2/|title=PAKISTAN ASSUMES COMMAND OF COMBINED TASK FORCE 151|date=September 28, 2011|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=October 13, 2011|archive-url=https://web.archive.org/web/20111013062804/https://combinedmaritimeforces.com/2011/09/28/pakistan-assumes-command-of-combined-task-force-151-2/}}</ref> * {{flagicon|Denmark}} Commodore Aage Buur Jensen, [[Danish Navy]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2012/01/12/denmark-assumes-command-of-combined-task-force-151-bahrain/|title=DENMARK ASSUMES COMMAND OF COMBINED TASK FORCE 151 BAHRAIN|date=January 12, 2012|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=March 10, 2012|archive-url=https://web.archive.org/web/20120310154427/https://combinedmaritimeforces.com/2012/01/12/denmark-assumes-command-of-combined-task-force-151-bahrain/}}</ref> * {{flagicon|Thailand}} Rear Admiral Tanin Likitawong, [[Royal Thai Navy|RTN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2012/03/29/royal-thai-navy-assumes-command-of-combined-task-force-151/|title=ROYAL THAI NAVY ASSUMES COMMAND OF COMBINED TASK FORCE 151|date=March 29, 2012|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=July 20, 2014|archive-url=https://web.archive.org/web/20140720100903/https://combinedmaritimeforces.com/2012/03/29/royal-thai-navy-assumes-command-of-combined-task-force-151/}}</ref> * {{flagicon|South Korea}} Rear Admiral Anho Chung, [[ROKN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2012/06/19/republic-of-korea-navy-assumes-command-of-combined-task-force-151/|title=REPUBLIC OF KOREA NAVY ASSUMES COMMAND OF COMBINED TASK FORCE 151|date=June 19, 2012|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=July 20, 2014|archive-url=https://web.archive.org/web/20140720085609/https://combinedmaritimeforces.com/2012/06/19/republic-of-korea-navy-assumes-command-of-combined-task-force-151/}}</ref> * {{flagicon|Turkey}} Rear Admiral Oguz Karaman, [[Turkish Navy|TN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2012/09/25/turkey-assumes-command-of-combined-task-force-151/|title=TURKEY ASSUMES COMMAND OF COMBINED TASK FORCE 151|date=September 25, 2012|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=September 14, 2015|archive-url=https://web.archive.org/web/20150914170918/https://combinedmaritimeforces.com/2012/09/25/turkey-assumes-command-of-combined-task-force-151/}}</ref> * {{flagicon|Pakistan}} Commodore Muhammad Hisham, [[Pakistan Navy|PN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2012/12/13/pakistan-navy-assumes-command-of-combined-task-force-151/|title=PAKISTAN NAVY ASSUMES COMMAND OF COMBINED TASK FORCE 151|date=December 13, 2012|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=December 16, 2012|archive-url=https://web.archive.org/web/20121216061305/https://combinedmaritimeforces.com/2012/12/13/pakistan-navy-assumes-command-of-combined-task-force-151/}}</ref> * {{flagicon|Singapore}} Rear Admiral Giam Hock Koon, [[Republic of Singapore Navy|RSN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2013/03/07/republic-of-singapore-navy-takes-command-of-combined-task-force-151/|title=REPUBLIC OF SINGAPORE NAVY TAKES COMMAND OF COMBINED TASK FORCE 151|date=March 7, 2013|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=March 26, 2013|archive-url=https://web.archive.org/web/20130326110019/https://combinedmaritimeforces.com/2013/03/07/republic-of-singapore-navy-takes-command-of-combined-task-force-151/}}</ref> * {{flagicon|Pakistan}} Commodore Muhammad Ihsan Qadir, [[Pakistan Navy|PN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2013/06/13/singapore-hands-over-ctf-151-to-pakistan/|title=Singapore hands over CTF 151 to Pakistan|date=June 13, 2013|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=July 25, 2014|archive-url=https://web.archive.org/web/20140725160114/https://combinedmaritimeforces.com/2013/06/13/singapore-hands-over-ctf-151-to-pakistan/}}</ref> * {{flagicon|UK}} Commodore Jeremy Blunden [[Lieutenant of the Royal Victorian Order|LVO]], [[Royal Navy|RN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2013/09/12/combined-task-force-151-change-of-command-ceremony/|title=Combined Task Force 151 Change of Command Ceremony|date=September 12, 2013|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=October 8, 2013|archive-url=https://web.archive.org/web/20131008153011/https://combinedmaritimeforces.com/2013/09/12/combined-task-force-151-change-of-command-ceremony/}}</ref> * {{flagicon|Denmark}} Commodore Aage Buur Jensen, [[Danish Navy]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2013/12/12/uk-handover-to-denmark-at-ctf-151-change-of-command-ceremony/|title=UK handover to Denmark at CTF 151 Change of Command Ceremony|date=December 12, 2013|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=December 12, 2013|archive-url=https://web.archive.org/web/20131212170618/https://combinedmaritimeforces.com/2013/12/12/uk-handover-to-denmark-at-ctf-151-change-of-command-ceremony/}}</ref> ''2nd Term'' * {{flagicon|Pakistan}} Commodore Ali Abbas SI(M), [[Pakistan Navy|PN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2014/03/02/denmark-handover-to-pakistan-at-ctf-151-change-of-command-ceremony/|title=Denmark handover to Pakistan at CTF 151 change of command ceremony|date=March 2, 2014|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=March 2, 2014|archive-url=https://web.archive.org/web/20140302125657/https://combinedmaritimeforces.com/2014/03/02/denmark-handover-to-pakistan-at-ctf-151-change-of-command-ceremony/}}</ref> * {{flagicon|South Korea}} Rear Admiral Cho Young Joo, [[ROKN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2014/06/18/pakistan-passes-command-of-ctf-151-to-the-republic-of-korea/|title=Pakistan passes command of CTF-151 to the Republic of Korea|date=June 18, 2014|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=July 1, 2014|archive-url=https://web.archive.org/web/20140701210346/https://combinedmaritimeforces.com/2014/06/18/pakistan-passes-command-of-ctf-151-to-the-republic-of-korea/}}</ref> * {{flagicon|New Zealand}} Commodore Tony Millar, [[New Zealand Order of Merit|MNZM]], [[Royal New Zealand Navy|RNZN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2014/09/02/south-korea-passes-command-of-ctf-151-to-new-zealand/|title=South Korea passes command of CTF-151 to New Zealand|date=September 2, 2014|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=October 14, 2014|archive-url=https://web.archive.org/web/20141014071120/https://combinedmaritimeforces.com/2014/09/02/south-korea-passes-command-of-ctf-151-to-new-zealand/}}</ref> * {{flagicon|Thailand}} Rear Admiral Pakorn Wanich, [[Royal Thai Navy|RTN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2014/11/25/new-zealand-passes-command-of-ctf-151-to-thailand/|title=New Zealand passes command of CTF-151 to Thailand|date=November 25, 2014|website=Combined Maritime Forces (CMF)|access-date=August 26, 2021|archive-date=December 7, 2014|archive-url=https://web.archive.org/web/20141207020132/https://combinedmaritimeforces.com/2014/11/25/new-zealand-passes-command-of-ctf-151-to-thailand/}}</ref> * {{flagicon|Pakistan}} Commodore Asif Hameed Siddiqui, [[Pakistan Navy|PN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2015/04/23/ukmto-dubai-welcomes-the-commander-of-the-combined-task-force-151/|title=UKMTO Dubai welcomes the Commander of the Combined Task Force 151.|date=April 23, 2015|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Japan}} Rear Admiral Hiroshi Ito, [[JMSDF]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2015/06/02/japan-makes-history-as-it-takes-the-lead-of-combined-task-force-151/|title=Japan Makes History as it Takes the Lead of Combined Task Force 151|date=June 2, 2015|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Turkey}} Captain Ayhan Bay, [[Turkish Navy|TN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2015/08/27/turkey-assumes-command-of-ctf-151-from-japan/|title=Turkey assumes command of CTF 151 from Japan|date=August 27, 2015|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Pakistan}} Rear Admiral [[Zahid Ilyas]], [[Pakistan Navy|PN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2015/12/21/pakistan-assumes-command-of-ctf-151-from-turkey/|title=Pakistan assumes command of CTF 151 from Turkey|date=December 21, 2015|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Singapore}} Rear Admiral Cheong Kwok Chien, [[Republic of Singapore Navy|RSN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2016/04/07/pakistan-handover-to-singapore-at-ctf-151-change-of-command-ceremony/|title=Pakistan handover to Singapore at CTF 151 Change of Command Ceremony|date=April 7, 2016|website=Combined Maritime Forces (CMF)}}</ref><ref>{{Cite web|url=https://www.mindef.gov.sg/oms/imindef/mindef_websites/atozlistings/saftimi/about_Us/Commandant_SAFTI_MI.html|title=Commandant SAFTI MI|website=www.mindef.gov.sg|access-date=2021-08-26|archive-date=2020-04-11|archive-url=https://web.archive.org/web/20200411191411/https://www.mindef.gov.sg/oms/imindef/mindef_websites/atozlistings/saftimi/about_Us/Commandant_SAFTI_MI.html|url-status=dead}}</ref> * {{flagicon|South Korea}} Rear Admiral Nam Dong Woo, [[ROKN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2016/07/07/singapore-handover-to-korea-at-ctf-151-change-of-command-ceremony/|title=Singapore handover to Korea at CTF 151 Change of Command Ceremony|date=July 7, 2016|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Pakistan}} Commodore Muhammad Shuaib SI (M), [[Pakistan Navy]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2016/10/27/ctf-151-handover-piracy-maritimesecurityoperations/|title=CTF 151 Handover #piracy #maritimesecurityoperations|date=October 27, 2016|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Japan}} Rear Admiral Tatsuya Fukuda, [[JMSDF]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2017/03/09/ctf-151-change-of-command-ceremony/|title=CTF 151 Change of Command Ceremony|date=March 9, 2017|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Turkey}} Rear Admiral Emre Sezenler, [[Turkish Navy|TN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2017/06/29/japan-hands-over-to-turkey-in-ctf151-change-of-command-ceremony/|title=JAPAN HANDS OVER TO TURKEY IN CTF151 CHANGE OF COMMAND CEREMONY|date=June 29, 2017|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Bahrain}} Commodore Yusuf Almannaei, [[Royal Bahrain Naval Force|RBNF]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2017/11/02/turkey-hands-over-to-bahrain-in-ctf-151-change-of-command-ceremony/|title=TURKEY HANDS OVER TO BAHRAIN IN CTF 151 CHANGE OF COMMAND CEREMONY|date=November 2, 2017|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Japan}} Rear Admiral Daisuke Kajimoto, [[JMSDF]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2018/03/01/ctf-151-bahrain-handover-to-japan/|title=CTF 151 BAHRAIN HANDOVER TO JAPAN|date=March 1, 2018|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Singapore}} Rear Admiral Saw Shi Tat, [[Republic of Singapore Navy|RSN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2018/07/01/singapore-takes-command-of-counter-piracy-combined-task-force-151/|title=SINGAPORE TAKES COMMAND OF COUNTER PIRACY COMBINED TASK FORCE 151|date=July 1, 2018|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Kuwait}} Captain Ali Al Rashidi, [[Kuwait Naval Force]]<ref name="auto1">{{Cite web|url=https://combinedmaritimeforces.com/2019/02/25/first-time-ctf-151-and-ctf-152-conducted-a-change-of-command-ceremony-on-the-same-day/|title=FIRST TIME CTF 151 AND CTF 152 CONDUCTED A CHANGE OF COMMAND CEREMONY ON THE SAME DAY!|date=February 25, 2019|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Kuwait}} Captain Alajmi, [[Kuwait Naval Force]]<ref name="auto1"/> * {{flagicon|South Korea}} Rear Admiral Byeong-Ju Yu, [[ROKN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2019/06/26/kuwait-naval-forces-hands-over-to-republic-of-korea-navy-in-ctf-151-change-of-command-ceremony/|title=Kuwait Naval Forces hands over to Republic of Korea Navy in CTF 151 Change of Command Ceremony|date=June 26, 2019|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Kuwait}} Captain Khaled Hasan Al Kandari, [[Kuwait Naval Force]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2019/10/23/republic-of-korea-navy-hands-over-command-of-ctf-151-to-kuwait-naval-force/|title=Republic of Korea Navy hands over command of CTF 151 to Kuwait Naval Force – القوات البحرية للجمهورية الكورية تسلم قيادة قوات الواجب المختلطة -١٥١ للقوات البحرية الكويتية|date=October 23, 2019|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Japan}} Rear Admiral Yoshiyasu Ishimaki, [[JMSDF]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2020/02/23/japan-takes-command-of-combined-task-force-151/|title=JAPAN TAKES COMMAND OF COMBINED TASK FORCE 151|date=February 23, 2020|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Turkey}} Rear Admiral Nejat Inanir, [[Turkish Navy|TN]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2020/07/21/japan-hands-over-command-of-ctf-151-to-turkey/|title=Japan Hands Over Command of CTF 151 to Turkey|date=July 21, 2020|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Pakistan}} Commodore Abdul Munib, [[Pakistan Navy]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2020/12/18/turkish-navy-hands-over-task-force-command-to-pakistan/|title=TURKISH NAVY HANDS OVER TASK FORCE COMMAND TO PAKISTAN|date=December 18, 2020|website=Combined Maritime Forces (CMF)}}</ref> * {{flagicon|Brazil}} Rear Admiral André Luiz Andrade Felix, [[Brazilian Navy]]<ref>{{Cite web|url=https://combinedmaritimeforces.com/2021/06/10/brazilian-navy-marihna-do-brasil-takes-first-command-in-cmf/|title=BRAZILIAN NAVY (MARIHNA DO BRASIL) TAKES FIRST COMMAND IN CMF|date=June 10, 2021|website=Combined Maritime Forces (CMF)}}</ref> '''(Current)''' == Command History == The Task Force has been headed by different countries participating.<ref>{{Cite web|url=https://combinedmaritimeforces.com/ctf-151-counter-piracy/|title=CTF 151: Counter-piracy Website|date=17 September 2010}}</ref> {{col-begin}} {{col-2}} {| class="wikitable" style="text-align:center" ! colspan="2" | Term of Command |- !Date !Country |- |11 January 2009 |USA |- |5 April 2009 |USA |- |3 May 2009 |Turkey |- |13 August 2009 |USA |- |20 January 2010 |Singapore |- |21 April 2010 |Republic of Korea |- |1 September 2010 |Turkey |- |29 November 2010 |Pakistan |- |31 March 2011 |Singapore |- |1 July 2011 |New Zealand |- |27 September 2011 |Pakistan |- |13 January 2012 |Denmark |- |29 March 2012 |Thailand |- |18 June 2012 |Republic of Korea |- |19 September 2012 |Turkey |- |13 December 2012 |Pakistan |- |7 March 2013 |Singapore |- |6 June 2013 |Pakistan |- |5 September 2013 |UK |- |12 December 2013 |Denmark |- |27 February 2014 |Pakistan |- |12 June 2014 |Republic of Korea |- |28 August 2014 |New Zealand |- |25 November 2014 |Thailand |- |26 February 2015 |Pakistan |- |31 May 2015 |Japan |- |27 August 2015 |Turkey |- |21 December 2015 |Pakistan |- |31 March 2016 |Singapore |- |30 June 2016 |Republic of Korea |- |27 October 2016 |Pakistan |- |9 March 2017 |Japan |- |29 June 2017 |Turkey |- |2 November 2017 |Bahrain |- |1 March 2018 |Japan |- |28 June 2018 |Singapore |- |27 September 2018 |Kuwait |- |21 February 2019 |Kuwait |- |20 June 2019 |Republic of Korea |- |20 October 2019 |Kuwait |- |20 February 2020 |Japan |- |21 July 2020 |Turkey |- |18 December 2020 |Pakistan |- |10 June 2021 |Brazil |} {{col-2}} {| class= "wikitable" style="text-align:center" |- !colspan= "2" | Command History |- !Country !No. of Times |- |Pakistan |9 |- |Turkey |6 |- |Republic of Korea |5 |- |Singapore |5 |- |Japan |4 |- |Kuwait |3 |- |USA |3 |- |Denmark |2 |- |New Zealand |2 |- |Thailand |2 |- |Bahrain |1 |- |Brazil |1 |- |UK |1 |} {{col-end}} ==See also== * [[Operation Atalanta]]—EU operation in the area * [[Operation Ocean Shield]]—NATO operation in the area * [[Combined Task Force 150]]—similar patrol in the Indian Ocean that deals with counter-terrorism * [[Maritime Security Patrol Area]] * [[Maersk Alabama hijacking|''Maersk Alabama'' hijacking]] in April 2009 ==References== {{Reflist|2}} ==Further reading== * McKnight, Terry and Michael Hirsh. ''Pirate Alley: Commanding Task Force 151 off Somalia.'' Annapolis, MD : Naval Institute Press, 2012. {{ISBN|1-61251-134-1}} {{ OCLC | 785079505}} * Newsome, Timothy E. ''Somali Piracy: Are We Making a Mountain Out of a Molehill?'' Ft. Belvoir: Defense Technical Information Center, 2009. {{ OCLC | 574551215}} * Phillips, Richard, and Stephan Talty. ''A Captain's Duty: Somali Pirates, Navy Seals, and Dangerous Days at Sea.'' New York: Hyperion, 2010. {{ISBN|1-4013-2380-4}} {{ OCLC | 430843212}} * Zogg, Dennis M. ''Why the U.S. Navy Should Not Be Fighting Piracy Off Somalia.'' Ft. Belvoir: Defense Technical Information Center, 2009. {{ OCLC | 465323456}} ==External links== {{Commons category}} *[https://abcnews.go.com/International/story?id=6919762 U.S. Navy Hunt for Somali Pirates: Behind the Pirate Code] *[http://www.africom.mil/Newsroom/Article/6412/centcom-new-counter-piracy-task-force-established CENTCOM: New Counter-Piracy Task Force Established] *[http://www.cnn.com/2009/WORLD/africa/01/08/piracy.task.force/ Navy creates force devoted to fighting piracy] *[http://combinedmaritimeforces.com/ctf-151-counter-piracy/ CTF-151: Counter-piracy] *[http://www.defense.gov/news/newsarticle.aspx?id=52586 Multinational Task Force Targets Pirates] *[http://www.foreignaffairs.com/articles/65173/thomas-culora-and-andrew-erickson/arms-and-influence-at-sea Arms and Influence at Sea] {{Webarchive|url=https://web.archive.org/web/20140808053233/http://www.foreignaffairs.com/articles/65173/thomas-culora-and-andrew-erickson/arms-and-influence-at-sea |date=2014-08-08 }} *[http://www.marsecreview.com/tag/ctf-151/ Tag Archive: CTF-151] {{Webarchive|url=https://web.archive.org/web/20210629115712/http://www.marsecreview.com/tag/ctf-151/ |date=2021-06-29 }} *[http://www.nato.int/structur/AC/141/pdf/PS-M/Combined%20Maritime%20Forces%20Ops.pdf Combined Maritime Forces (CMF)Operations Counter Piracy Operations, Challenges, Shortfalls and Lessons Learned] {{Webarchive|url=https://web.archive.org/web/20120524031858/http://www.nato.int/structur/AC/141/pdf/PS-M/Combined%20Maritime%20Forces%20Ops.pdf |date=2012-05-24 }} *[http://www.navy.mil/submit/display.asp?story_id=41687 New Counter-Piracy Task Force Established] {{Webarchive|url=https://web.archive.org/web/20120629205022/http://www.navy.mil/submit/display.asp?story_id=41687 |date=2012-06-29 }} *[http://www.seapowermagazine.org/sas/stories/20130409-pirates.html Counter-piracy Mission Off Somalia Remains Problematic] {{Webarchive|url=https://web.archive.org/web/20131204060220/http://www.seapowermagazine.org/sas/stories/20130409-pirates.html |date=2013-12-04 }} *[https://2009-2017.state.gov/t/pm/ppa/piracy/c32662.htm The United States Response to Piracy off the Coast of Somalia] *[http://www.stripes.com/news/combined-task-force-151-hunts-down-pirates-in-the-gulf-of-aden-1.89695 Combined Task Force 151 hunts down pirates in the Gulf of Aden] {{Authority control}} [[Category:Multinational units and formations]] [[Category:Naval operations involving Pakistan]] [[Category:Naval task forces]] [[Category:Piracy in Somalia]] [[Category:Military units and formations established in 2009]] nbuybnw1yvzmt9oyzh29e1s856t5v7g NodeMW client 0 127112 769832 769495 2026-10-23T09:35:02Z ~2026-56685-09 76379 Testing nodemw client 769832 wikitext text/x-wiki Test Content 11217 --[[Special:Contributions/~2026-56685-09|~2026-56685-09]] ([[User talk:~2026-56685-09|talk]]) 09:35, 23 October 2026 (UTC) gg8m6algro7tap4onzk3go9e72rpxek File:MP sounds-pwb.png 6 152343 769757 769384 2026-10-22T13:08:43Z Pywikibot-test 23124 Pywikibot-test uploaded a new version of [[File:MP sounds-pwb.png]] 764329 wikitext text/x-wiki Flaticon is fine and we are working in der nãhe in gc94fkpyui3h0farq9cef4ji1hk3ari 769758 769757 2026-10-22T13:09:22Z Pywikibot-test 23124 Pywikibot-test uploaded a new version of [[File:MP sounds-pwb.png]] 764329 wikitext text/x-wiki Flaticon is fine and we are working in der nãhe in gc94fkpyui3h0farq9cef4ji1hk3ari File:MP sounds-pwb-chunked.png 6 155656 769759 769385 2026-10-22T13:09:43Z Pywikibot-test 23124 Pywikibot-test uploaded a new version of [[File:MP sounds-pwb-chunked.png]] 764321 wikitext text/x-wiki pywikibot test [[Category:speaker]] aozwwno2cjpgcdi00uxzsb2sf3vck96 User:Unicodesnowman/DeleteMark 2 166403 769752 769379 2026-10-22T13:03:58Z Pywikibot-test 23124 pywikibot unit test. Do NOT actually delete. 769752 wikitext text/x-wiki {{delete|1=pywikibot unit test. Do NOT actually delete.}} Pywikibot deletion test. dcftqsyyicveaaxsx5yic8hvklv2iue 769753 769752 2026-10-22T13:04:08Z Pywikibot-test 23124 Pywikibot unit test 769753 wikitext text/x-wiki Pywikibot deletion test. l5a6iw696mbwr7beiudqo7xxpg7k54m Reflective (Backstreet Girls album) 0 177739 769764 765397 2026-10-22T15:39:11Z ~2026-56279-63 76369 /* Track listing */ 769764 wikitext text/x-wiki {{Use American English|date=December 2022}} {{Use mdy dates|date=September 2017}} {{Infobox album | name = Reflective | type = studio | artist = [[Backstreet Girls (girl group)|Backstreet Girls]] | cover = | border = | alt = | caption = | released = {{Start date|2005|01|30}} | recorded = March–August 2004 | studio = | genre = * [[Pop music|Pop]] * [[dance-pop]] * [[comedy pop]] * [[Contemporary R&B|R&B]] | length = | label = * [[Columbia Records|Columbia]] * [[Syco Music|Syco]] | producer = * [[Brothers in Rhythm]] * [[Graham Stack (music producer)|Graham Stack]] * [[Brian Rawling]] * [[Mark Taylor (music producer)|Mark Taylor]] * Steve Morales * [[Jimmy Jam and Terry Lewis]] * [[Monte Moir]] * [[Cory Rooney]] * [[Troy Oliver]] * Malik Pendleton * [[Dinky Bingham]] * [[Scott Storch]] * [[Steve Mac]] * [[Rich Harrison]] * Phillip "Silky" White * [[Warryn Campbell|Warryn "Baby Dubb" Campbell]] | prev_title = [[Better Tomorrow (EP)|Better Tomorrow]] | prev_year = 2003 | next_title = [[7/24]] | next_year = 2006 | misc = {{Singles | name = Reflective | type = studio | single1 = [[Escape (Backstreet Girls song)|Escape]] | single1date = July 7, 2004 | single2 = [[A Little Bit (song)|A Little Bit]] | single2date = October 28, 2004 | single3 = [[All for You (Backstreet Girls song)|All for You]] | single3date = January 19, 2005 }} }} '''''Reflective''''' is the debut studio album by American comedy girl group [[Backstreet Girls (girl group)|Backstreet Girls]]. It was released on January 30, 2005, by [[Syco Music]] and [[Columbia Records]]. Lyrically, the album discusses themes of female-empowerment, romance, heartbreak and confidence. Musically, ''Reflective'' is primarily a [[pop music|pop]] record and showcases [[synthpop]], "grungy" [[Hip hop music|hip hop]] and [[Contemporary R&B|R&B]] sounds. The album features [[guest appearance]]s by Puerto Rican rapper [[Daddy Yankee]], American rapper [[Fat Joe]], as well as American singer-songwriter [[Jennifer Lopez]], and collaborations with several [[record producer|producers]] including [[Monte Moir]], [[Cory Rooney]] and [[Jimmy Jam and Terry Lewis]]. ==Background and release== ==Recording and development== ==Composition== ===Music and lyrics=== ===Songs and lyrical content=== ==Singles== ===Promotional singles=== ==Promotion== {{Main|The Reflective Tour}} ==Track listing== {{Track listing | headline = ''Reflective''{{nobold|&nbsp;– Standard edition}} | extra_column = Producer(s) | total_length = | title1 = Whatever Makes You Happy | writer1 = {{flatlist| * [[Steve Anderson (musician)|Steve Anderson]] * [[Dave Seaman]] * Alan Bremner * [[Dannii Minogue]] }} | extra1 = [[Brothers in Rhythm]] | length1 = | title2 = [[Escape (Backstreet Girls song)|Escape]] | writer2 = {{flatlist| * [[Graham Stack (record producer)|Graham Stack]] * Brian Rawling * [[Mark Taylor (producer)|Mark Taylor]] * [[Enrique Iglesias]] * Ira Shickman * [[Karen Poole]] }} | extra2 = {{flatlist| * [[Graham Stack (record producer)|Graham Stack]] * Brian Rawling * [[Mark Taylor (producer)|Mark Taylor]] * [[Karen Poole]]{{ref|b|[b]}} }} | length2 = | title3 = [[A Little Bit (song)|A Little Bit]] | writer3 = {{flatlist| * Steve Morales * [[Jennifer Lopez]] * [[David Siegel (musician)|David Siegel]] }} | extra3 = {{flatlist| * Steve Morales * [[Jim Beanz]]{{ref|b|[b]}} }} | length3 = | title4 = [[All for You (Backstreet Girls song)|All for You]] | note4 = featuring [[Daddy Yankee]] | writer4 = {{flatlist| * [[Rebbie Jackson]] * [[Jimmy Jam and Terry Lewis|James Harris III]] * [[Jimmy Jam and Terry Lewis|Terry Lewis]] * [[Monte Moir]] }} | extra4 = {{flatlist| * [[Jimmy Jam and Terry Lewis]] * [[Monte Moir]]{{ref|a|[a]}} * [[The Avila Brothers|Bobby Ross Avila & Iz]]{{ref|c|[c]}} }} | length4 = | title5 = Situation's Heavy | writer5 = {{flatlist| * [[Cory Rooney]] * [[Jordan Knight]] * [[Troy Oliver]] }} | extra5 = {{flatlist| * [[Cory Rooney]] * [[Troy Oliver]] * [[Jack Knight (songwriter)|Jack Knight]]{{ref|d|[d]}} }} | length5 = | title6 = Million Different Ways | writer6 = {{flatlist| * [[Mary Brown (songwriter)|Mary Brown]] * Alvin West }} | extra6 = {{flatlist| * Malik Pendleton * [[Dinky Bingham]] }} | length6 = | title7 = We Could Have It All | note7 = featuring [[Fat Joe]] | writer7 = {{flatlist| * [[Scott Storch]] * Steve Torch * [[Robert Waller (musician)|Robert Waller]] * [[Fat Joe|Joseph Cartagena]] * [[Rodney Jerkins]] * [[LaShawn Daniels]] * Rooney * Lopez * [[Fred Jerkins III]] }} | extra7 = [[Scott Storch]] | length7 = | title8 = Conversation's Over | writer8 = {{flatlist| * [[Wayne Hector]] * Brown * [[Steve Mac]] * [[Andrea Martin (musician)|Andrea Martin]] * [[Ivan Matias]] }} | extra8 = {{flatlist| * [[Steve Mac]] * [[Mary Brown (songwriter)|Mary Brown]]{{ref|b|[b]}} }} | length8 = | title9 = Nasty Ghetto | writer9 = {{flatlist| * [[Rich Harrison]] * Shickman * Brown }} | extra9 = {{flatlist| * [[Rich Harrison]] * Brown{{ref|b|[b]}} }} | length9 = | title10 = Sometimes | writer10 = {{flatlist| * Lopez * Phillip White }} | extra10 = Phillip "Silky" White | length10 = | title11 = Maya | writer11 = {{flatlist| * Brown * [[Nick Lachey]] * [[Teddy Riley]] * [[Bink (producer)|Roosevelt Harrell]] * [[Blackstreet|Chauncey Hannibal]] * Karen Anderson * [[Bunny DeBarge|Etterlene DeBarge]] }} | extra11 = Pendleton | length11 = | all_writing = }} {{Track listing | headline = ''Reflective''{{nobold|&nbsp;– Deluxe edition}} | extra_column = Producer(s) | total_length = | title12 = Twisted | writer12 = {{flatlist| * [[Makeba Riddick]] * [[Brooke Hogan]] * Jackson * White }} | extra12 = {{flatlist| * White * [[Makeba Riddick]]{{ref|b|[b]}} * [[Brooke Hogan]]{{ref|b|[b]}} * [[Rebbie Jackson]]{{ref|b|[b]}} * Poole{{ref|b|[b]}} }} | length12 = | title13 = Buster | writer13 = {{Flat list | * [[Warryn Campbell]] * Knight * Harris III * Lewis }} | extra13 = [[Warryn Campbell|Warryn "Baby Dubb" Campbell]] | length13 = | title14 = More Than a Million Miles | note14 = featuring [[Jennifer Lopez]] | writer14 = {{Flat list | * Lopez * [[Babyface (musician)|Kenneth Edmonds]] * [[Bryce Wilson]] }} | extra14 = {{Flat list | * White * Jennifer Lopez{{ref|b|[b]}} * Poole{{ref|b|[b]}} }} | length14 = }} '''Notes'''<ref name="credits">{{cite AV media notes|others=[[Backstreet Girls (girl group)|Backstreet Girls]]|title=Reflective|year=2005|type=booklet|publisher=Syco Entertainment, Columbia, Sony Music|id=88875021222}}</ref> * <sup>{{note|a|[a]}}</sup> signifies a co-producer. * <sup>{{note|b|[b]}}</sup> signifies a vocal producer. * <sup>{{note|c|[c]}}</sup> signifies an additional producer. * <sup>{{note|d|[d]}}</sup> signifies an additional vocal producer. '''Sample credits''' * "We Could Have It All" contains elements of the composition "[[If You Had My Love]]", written by [[Rodney Jerkins]], [[LaShawn Daniels]], [[Cory Rooney]], [[Jennifer Lopez]] and [[Fred Jerkins III]], performed by Jennifer Lopez. * "Maya" contains a portion of the composition "[[Don't Leave Me (Blackstreet song)|Don't Leave Me]]", written by [[Teddy Riley]], [[Bink (producer)|Roosevelt Harrell]], [[Blackstreet|Chauncey Hannibal]], Karen Anderson and [[Bunny DeBarge]], performed by [[Blackstreet]]. * "Buster" contains an interpolation from "[[Human (The Human League song)|Human]]", written by [[Jimmy Jam and Terry Lewis|James Harris III]] and [[Jimmy Jam and Terry Lewis|Terry Lewis]], performed by [[The Human League]]. * "More Than a Million Miles" contains a portion of the composition "[[You're Makin' Me High]]", written by [[Babyface (musician)|Kenneth Edmonds]] and [[Bryce Wilson]], performed by [[Toni Braxton]]. ==Charts== ===Weekly charts=== ===Year-end charts=== ==Certifications== ==Release history== ==References== {{Backstreet Girls (girl group)}} {{Authority control}} [[Category:2005 debut albums]] [[Category:Backstreet Girls (girl group) albums]] [[Category:Columbia Records albums]] [[Category:Albums produced by Jim Beanz]] [[Category:Albums produced by Jimmy Jam and Terry Lewis]] [[Category:Albums produced by Cory Rooney]] [[Category:Albums produced by Troy Oliver]] [[Category:Albums produced by Scott Storch]] 15kvojdmoghvoy9ai972nh26xpb7o3b 7/24 0 177741 769819 768623 2026-10-23T01:25:44Z ~2026-56530-26 76376 /* Track listing */ 769819 wikitext text/x-wiki {{short description|2006 studio album by Backstreet Girls}} {{about|the Backstreet Girls album|the date|July 24|other uses|724 (disambiguation)}} {{good article}} {{Use mdy dates|date=September 2019}} {{Infobox album | name = 7/24 | type = studio | artist = [[Backstreet Girls (girl group)|Backstreet Girls]] | cover = | border = | alt = | caption = | released = {{start date|2006|05|27}} | recorded = September–December 2005 | venue = | studio = | genre = {{flatlist| * [[Pop music|Pop]] * [[tropical house]] * [[comedy pop]] * [[Contemporary R&B|R&B]] }} | length = | label = {{flatlist| * [[Columbia Records|Columbia]] * [[Syco Music|Syco]] }} | producer = {{flatlist| * [[Rob Dougan]] * [[Rhett Lawrence]] * [[Manuel Seal]] * Eric Seats * Jeremy Harding * [[Linda Perry]] * Malik Pendleton * Rapture Stewart * [[Dallas Austin]] * [[Jimmy Harry]] * [[Soulshock and Karlin]] * [[Just Blaze]] * [[Jimmy Jam and Terry Lewis]] }} | prev_title = [[Reflective (Backstreet Girls album)|Reflective]] | prev_year = 2005 | next_title = [[Backstreet Girls (album)|Backstreet Girls]] | next_year = 2007 | misc = {{Singles | name = 7/24 | type = Studio | single1 = [[Irresistible (Backstreet Girls song)|Irresistible]] | single1date = February 26, 2006 | single2 = [[All Nite (Don't Stop) (song)|All Nite (Don't Stop)]] | single2date = May 31, 2006 | single3 = [[Satisfied (Backstreet Girls song)|Satisfied]] | single3date = September 27, 2006 }} }} '''''7/24''''' is the second studio album by American comedy girl group [[Backstreet Girls (girl group)|Backstreet Girls]], released by [[Syco Music]] and [[Columbia Records]] on May 27, 2006. The record is the follow-up to the group's debut studio album ''[[Reflective (Backstreet Girls album)|Reflective]]'' (2005). Its lyrics discuss themes of [[female empowerment]] and love. It features guest appearances by American [[dancehall]] and [[hip hop]] artists [[Elephant Man]], [[Sean Paul]] and [[Method Man]], and collaborations with [[Record producer|producers]] [[Manuel Seal]], [[Dallas Austin]] and [[Jimmy Jam and Terry Lewis]]. ''7/24'' is primarily a [[Pop music|pop]], [[tropical house]] and [[Contemporary R&B|R&B]] record that includes elements of [[reggae]], [[funk]], [[electronic dance music]], [[hip hop]] and [[Trap music (EDM)|trap]]. Unlike the genres explored on ''Reflective'', ''7/24''{{'s}} songs incorporate new genres like tropical house. This is the first Backstreet Girls album to feature [[Carmen Electra]] before she left the group in December 2006 to pursue a solo career. == Background and production == ==Recording== ==Title and artwork== ==Composition== ===Music and lyrics=== ===Songs and lyrical content=== == Release and promotion == == Singles == ===Promotional singles=== == Track listing == {{Track listing | headline = Standard edition<ref name = "Album booklet">{{cite AV media notes |title = 7/24 |year = 2006 |type = booklet |publisher = [[Syco Music|Syco]]}}</ref> | extra_column = Producer(s) | total_length = | title_width = 30% | writing_width = 70% | title1 = [[Satisfied (Backstreet Girls song)|Satisfied]] | writer1 = {{hlist|[[Pink (singer)|Alecia Moore]]|[[Rhett Lawrence]]|[[Jimmy Harry]]}} | extra1 = {{hlist|[[Jimmy Harry]]|[[Rhett Lawrence]]|[[Siobhan Fahey]]{{ref|a|[a]}}}} | length1 = | title2 = [[Irresistible (Backstreet Girls song)|Irresistible]] | note2 = featuring [[Elephant Man]] | writer2 = {{hlist|Eric Seats|[[Tweet (singer)|Clarlene Keys]]|[[Elephant Man|O'Neil Bryan]]|[[Timbaland & Magoo|Melvin Barcliff]]|Rapture Stewart|Hannon Lane}} | extra2 = {{hlist|Eric Seats|Rapture Stewart|[[Mary Brown (songwriter)|Mary Brown]]{{ref|a|[a]}}}} | length2 = | title3 = [[Models (Backstreet Girls song)|Models]] | writer3 = {{hlist|Moore|Lawrence|Harry}} | extra3 = {{hlist|Harry|Fahey{{ref|a|[a]}}}} | length3 = | title4 = [[Candy (Backstreet Girls song)|Candy]] | writer4 = {{hlist|[[Jimmy Jam and Terry Lewis|James Harris III]]|[[Jimmy Jam and Terry Lewis|Terry Lewis]]|[[Dallas Austin]]|[[Rebbie Jackson]]|[[Debra Killings]]}} | extra4 = {{hlist|[[Jimmy Jam and Terry Lewis]]|[[Dallas Austin]]}} | length4 = | title5 = Wild Horses | writer5 = {{hlist|[[Wayne Hector]]|Barcliff|[[Soulshock|Carsten Schack]]|[[Kenneth Karlin]]|[[Louis Biancaniello]]|[[Sam Watters]]}} | extra5 = {{hlist|[[Soulshock and Karlin]]|[[Louis Biancaniello]]|[[Sam Watters]]|[[Wayne Hector]]{{ref|a|[a]}}}} | length5 = | title6 = [[All Nite (Don't Stop (song)|All Nite (Don't Stop)]] | note6 = featuring [[Sean Paul]] | writer6 = {{hlist|Harris III|Lewis|Jason Henriques|Jeremy Harding|[[Cham (singer)|Damon Beckett]]|[[Just Blaze|Justin Smith]]|[[Solange Knowles]]|[[Sean Paul|Sean Henriques]]|[[Babyface (musician)|Kenneth Edmonds]]|[[Pharrell Williams]]|[[Chad Hugo]]}} | extra6 = {{hlist|Jimmy Jam and Terry Lewis|Jeremy Harding|[[Just Blaze]]{{ref|b|[b]}}|Brown{{ref|a|[a]}}}} | length6 = | title7 = Money | writer7 = {{hlist|Harris III|Lewis|Austin|Jackson|Killings|Smith}} | extra7 = {{hlist|Jimmy Jam and Terry Lewis|Austin}} | length7 = | title8 = Watch Me Go | writer8 = {{hlist|[[Morris Day]]|[[Jesse Johnson (musician)|Jesse Johnson]]|[[Jellybean Johnson]]}} | extra8 = Jimmy Jam and Terry Lewis | length8 = | title9 = Waiting | writer9 = {{hlist|Harris III|Lewis|Moore|[[Linda Perry]]|[[Cathy Dennis]]}} | extra9 = {{hlist|Jimmy Jam and Terry Lewis|[[Linda Perry]]|Brown{{ref|a|[a]}}}} | length9 = | title10 = Release Yo' Self | note10 = featuring [[Method Man]] | writer10 = {{hlist|[[Rob Dougan]]|[[Amerie|Amerie Rogers]]|[[Street Life (rapper)|Patrick Charles]]|[[Method Man|Clifford Smith]]}} | extra10 = {{hlist|[[Rob Dougan]]|[[Jack Knight (songwriter)|Jack Knight]]{{ref|a|[a]}}}} | length10 = }} {{track listing | headline = Deluxe edition<ref name = "Deluxe"> | extra_column = Producer(s) | total_length = | title_width = 30% | writing_width = 70% | title11 = Swinging London Town | writer11 = {{hlist|[[Manuel Seal]]|[[Solange Knowles]][[Robert Waller (musician)|Robert Waller]]}} | extra11 = {{hlist|[[Manuel Seal]]|[[Solange Knowles]]{{ref|a|[a]}}|[[Robert Waller (musician)|Robert Waller]]{{ref|a|[a]}}|[[Karen Poole]]{{ref|a|[a]}}}} | length11 = | title12 = It's Magic | writer12 = [[Mary Brown (songwriter)|Mary Brown]] | extra12 = {{hlist|Malik Pendleton|Brown{{ref|a|[a]}}}} | length12 = }} ==Notes== * <sup>{{note|a|[a]}}</sup> signifies a vocal producer. * <sup>{{note|b|[b]}}</sup> signifies an additional producer. ===Sample credits=== * "All Nite (Don't Stop)" contains a portion of the composition "[[There She Goes (Babyface song)|There She Goes]]", written by [[Babyface (musician)|Kenneth Edmonds]], [[Pharrell Williams]] and [[Chad Hugo]]. == Personnel == == Charts == === Weekly charts === === Year-end charts === == Certifications and sales == ==Notes== {{reflist|group=note}} == References == {{Reflist}} {{Backstreet Girls (girl group)|state=collapsed}} {{Authority control}} {{DEFAULTSORT:7 24}} [[Category:2006 albums]] [[Category:Backstreet Girls (girl group) albums]] [[Category:Columbia Records albums]] [[Category:Tropical house albums]] [[Category:House music albums by American artists]] [[Category:Contemporary R&B albums by American artists]] jisjbimdqc9s4ygb21k074uz9m32oo3 769820 769819 2026-10-23T01:26:08Z ~2026-56530-26 76376 /* Track listing */ 769820 wikitext text/x-wiki {{short description|2006 studio album by Backstreet Girls}} {{about|the Backstreet Girls album|the date|July 24|other uses|724 (disambiguation)}} {{good article}} {{Use mdy dates|date=September 2019}} {{Infobox album | name = 7/24 | type = studio | artist = [[Backstreet Girls (girl group)|Backstreet Girls]] | cover = | border = | alt = | caption = | released = {{start date|2006|05|27}} | recorded = September–December 2005 | venue = | studio = | genre = {{flatlist| * [[Pop music|Pop]] * [[tropical house]] * [[comedy pop]] * [[Contemporary R&B|R&B]] }} | length = | label = {{flatlist| * [[Columbia Records|Columbia]] * [[Syco Music|Syco]] }} | producer = {{flatlist| * [[Rob Dougan]] * [[Rhett Lawrence]] * [[Manuel Seal]] * Eric Seats * Jeremy Harding * [[Linda Perry]] * Malik Pendleton * Rapture Stewart * [[Dallas Austin]] * [[Jimmy Harry]] * [[Soulshock and Karlin]] * [[Just Blaze]] * [[Jimmy Jam and Terry Lewis]] }} | prev_title = [[Reflective (Backstreet Girls album)|Reflective]] | prev_year = 2005 | next_title = [[Backstreet Girls (album)|Backstreet Girls]] | next_year = 2007 | misc = {{Singles | name = 7/24 | type = Studio | single1 = [[Irresistible (Backstreet Girls song)|Irresistible]] | single1date = February 26, 2006 | single2 = [[All Nite (Don't Stop) (song)|All Nite (Don't Stop)]] | single2date = May 31, 2006 | single3 = [[Satisfied (Backstreet Girls song)|Satisfied]] | single3date = September 27, 2006 }} }} '''''7/24''''' is the second studio album by American comedy girl group [[Backstreet Girls (girl group)|Backstreet Girls]], released by [[Syco Music]] and [[Columbia Records]] on May 27, 2006. The record is the follow-up to the group's debut studio album ''[[Reflective (Backstreet Girls album)|Reflective]]'' (2005). Its lyrics discuss themes of [[female empowerment]] and love. It features guest appearances by American [[dancehall]] and [[hip hop]] artists [[Elephant Man]], [[Sean Paul]] and [[Method Man]], and collaborations with [[Record producer|producers]] [[Manuel Seal]], [[Dallas Austin]] and [[Jimmy Jam and Terry Lewis]]. ''7/24'' is primarily a [[Pop music|pop]], [[tropical house]] and [[Contemporary R&B|R&B]] record that includes elements of [[reggae]], [[funk]], [[electronic dance music]], [[hip hop]] and [[Trap music (EDM)|trap]]. Unlike the genres explored on ''Reflective'', ''7/24''{{'s}} songs incorporate new genres like tropical house. This is the first Backstreet Girls album to feature [[Carmen Electra]] before she left the group in December 2006 to pursue a solo career. == Background and production == ==Recording== ==Title and artwork== ==Composition== ===Music and lyrics=== ===Songs and lyrical content=== == Release and promotion == == Singles == ===Promotional singles=== == Track listing == {{Track listing | headline = Standard edition<ref name = "Album booklet">{{cite AV media notes |title = 7/24 |year = 2006 |type = booklet |publisher = [[Syco Music|Syco]]}}</ref> | extra_column = Producer(s) | total_length = | title_width = 30% | writing_width = 70% | title1 = [[Satisfied (Backstreet Girls song)|Satisfied]] | writer1 = {{hlist|[[Pink (singer)|Alecia Moore]]|[[Rhett Lawrence]]|[[Jimmy Harry]]}} | extra1 = {{hlist|[[Jimmy Harry]]|[[Rhett Lawrence]]|[[Siobhan Fahey]]{{ref|a|[a]}}}} | length1 = | title2 = [[Irresistible (Backstreet Girls song)|Irresistible]] | note2 = featuring [[Elephant Man]] | writer2 = {{hlist|Eric Seats|[[Tweet (singer)|Clarlene Keys]]|[[Elephant Man|O'Neil Bryan]]|[[Timbaland & Magoo|Melvin Barcliff]]|Rapture Stewart|Hannon Lane}} | extra2 = {{hlist|Eric Seats|Rapture Stewart|[[Mary Brown (songwriter)|Mary Brown]]{{ref|a|[a]}}}} | length2 = | title3 = [[Models (Backstreet Girls song)|Models]] | writer3 = {{hlist|Moore|Lawrence|Harry}} | extra3 = {{hlist|Harry|Fahey{{ref|a|[a]}}}} | length3 = | title4 = [[Candy (Backstreet Girls song)|Candy]] | writer4 = {{hlist|[[Jimmy Jam and Terry Lewis|James Harris III]]|[[Jimmy Jam and Terry Lewis|Terry Lewis]]|[[Dallas Austin]]|[[Rebbie Jackson]]|[[Debra Killings]]}} | extra4 = {{hlist|[[Jimmy Jam and Terry Lewis]]|[[Dallas Austin]]}} | length4 = | title5 = Wild Horses | writer5 = {{hlist|[[Wayne Hector]]|Barcliff|[[Soulshock|Carsten Schack]]|[[Kenneth Karlin]]|[[Louis Biancaniello]]|[[Sam Watters]]}} | extra5 = {{hlist|[[Soulshock and Karlin]]|[[Louis Biancaniello]]|[[Sam Watters]]|[[Wayne Hector]]{{ref|a|[a]}}}} | length5 = | title6 = [[All Nite (Don't Stop (song)|All Nite (Don't Stop)]] | note6 = featuring [[Sean Paul]] | writer6 = {{hlist|Harris III|Lewis|Jason Henriques|Jeremy Harding|[[Cham (singer)|Damon Beckett]]|[[Just Blaze|Justin Smith]]|[[Solange Knowles]]|[[Sean Paul|Sean Henriques]]|[[Babyface (musician)|Kenneth Edmonds]]|[[Pharrell Williams]]|[[Chad Hugo]]}} | extra6 = {{hlist|Jimmy Jam and Terry Lewis|Jeremy Harding|[[Just Blaze]]{{ref|b|[b]}}|Brown{{ref|a|[a]}}}} | length6 = | title7 = Money | writer7 = {{hlist|Harris III|Lewis|Austin|Jackson|Killings|Smith}} | extra7 = {{hlist|Jimmy Jam and Terry Lewis|Austin}} | length7 = | title8 = Watch Me Go | writer8 = {{hlist|[[Morris Day]]|[[Jesse Johnson (musician)|Jesse Johnson]]|[[Jellybean Johnson]]}} | extra8 = Jimmy Jam and Terry Lewis | length8 = | title9 = Waiting | writer9 = {{hlist|Harris III|Lewis|Moore|[[Linda Perry]]|[[Cathy Dennis]]}} | extra9 = {{hlist|Jimmy Jam and Terry Lewis|[[Linda Perry]]|Brown{{ref|a|[a]}}}} | length9 = | title10 = Release Yo' Self | note10 = featuring [[Method Man]] | writer10 = {{hlist|[[Rob Dougan]]|[[Amerie|Amerie Rogers]]|[[Street Life (rapper)|Patrick Charles]]|[[Method Man|Clifford Smith]]}} | extra10 = {{hlist|[[Rob Dougan]]|[[Jack Knight (songwriter)|Jack Knight]]{{ref|a|[a]}}}} | length10 = }} {{track listing | headline = Deluxe edition<refname = "Deluxe"> | extra_column = Producer(s) | total_length = | title_width = 30% | writing_width = 70% | title11 = Swinging London Town | writer11 = {{hlist|[[Manuel Seal]]|[[Solange Knowles]][[Robert Waller (musician)|Robert Waller]]}} | extra11 = {{hlist|[[Manuel Seal]]|[[Solange Knowles]]{{ref|a|[a]}}|[[Robert Waller (musician)|Robert Waller]]{{ref|a|[a]}}|[[Karen Poole]]{{ref|a|[a]}}}} | length11 = | title12 = It's Magic | writer12 = [[Mary Brown (songwriter)|Mary Brown]] | extra12 = {{hlist|Malik Pendleton|Brown{{ref|a|[a]}}}} | length12 = }} ==Notes== * <sup>{{note|a|[a]}}</sup> signifies a vocal producer. * <sup>{{note|b|[b]}}</sup> signifies an additional producer. ===Sample credits=== * "All Nite (Don't Stop)" contains a portion of the composition "[[There She Goes (Babyface song)|There She Goes]]", written by [[Babyface (musician)|Kenneth Edmonds]], [[Pharrell Williams]] and [[Chad Hugo]]. == Personnel == == Charts == === Weekly charts === === Year-end charts === == Certifications and sales == ==Notes== {{reflist|group=note}} == References == {{Reflist}} {{Backstreet Girls (girl group)|state=collapsed}} {{Authority control}} {{DEFAULTSORT:7 24}} [[Category:2006 albums]] [[Category:Backstreet Girls (girl group) albums]] [[Category:Columbia Records albums]] [[Category:Tropical house albums]] [[Category:House music albums by American artists]] [[Category:Contemporary R&B albums by American artists]] 0nqv6xlr5r98992manuj9upnegf81nu 769821 769820 2026-10-23T01:27:01Z ~2026-56530-26 76376 /* Track listing */ 769821 wikitext text/x-wiki {{short description|2006 studio album by Backstreet Girls}} {{about|the Backstreet Girls album|the date|July 24|other uses|724 (disambiguation)}} {{good article}} {{Use mdy dates|date=September 2019}} {{Infobox album | name = 7/24 | type = studio | artist = [[Backstreet Girls (girl group)|Backstreet Girls]] | cover = | border = | alt = | caption = | released = {{start date|2006|05|27}} | recorded = September–December 2005 | venue = | studio = | genre = {{flatlist| * [[Pop music|Pop]] * [[tropical house]] * [[comedy pop]] * [[Contemporary R&B|R&B]] }} | length = | label = {{flatlist| * [[Columbia Records|Columbia]] * [[Syco Music|Syco]] }} | producer = {{flatlist| * [[Rob Dougan]] * [[Rhett Lawrence]] * [[Manuel Seal]] * Eric Seats * Jeremy Harding * [[Linda Perry]] * Malik Pendleton * Rapture Stewart * [[Dallas Austin]] * [[Jimmy Harry]] * [[Soulshock and Karlin]] * [[Just Blaze]] * [[Jimmy Jam and Terry Lewis]] }} | prev_title = [[Reflective (Backstreet Girls album)|Reflective]] | prev_year = 2005 | next_title = [[Backstreet Girls (album)|Backstreet Girls]] | next_year = 2007 | misc = {{Singles | name = 7/24 | type = Studio | single1 = [[Irresistible (Backstreet Girls song)|Irresistible]] | single1date = February 26, 2006 | single2 = [[All Nite (Don't Stop) (song)|All Nite (Don't Stop)]] | single2date = May 31, 2006 | single3 = [[Satisfied (Backstreet Girls song)|Satisfied]] | single3date = September 27, 2006 }} }} '''''7/24''''' is the second studio album by American comedy girl group [[Backstreet Girls (girl group)|Backstreet Girls]], released by [[Syco Music]] and [[Columbia Records]] on May 27, 2006. The record is the follow-up to the group's debut studio album ''[[Reflective (Backstreet Girls album)|Reflective]]'' (2005). Its lyrics discuss themes of [[female empowerment]] and love. It features guest appearances by American [[dancehall]] and [[hip hop]] artists [[Elephant Man]], [[Sean Paul]] and [[Method Man]], and collaborations with [[Record producer|producers]] [[Manuel Seal]], [[Dallas Austin]] and [[Jimmy Jam and Terry Lewis]]. ''7/24'' is primarily a [[Pop music|pop]], [[tropical house]] and [[Contemporary R&B|R&B]] record that includes elements of [[reggae]], [[funk]], [[electronic dance music]], [[hip hop]] and [[Trap music (EDM)|trap]]. Unlike the genres explored on ''Reflective'', ''7/24''{{'s}} songs incorporate new genres like tropical house. This is the first Backstreet Girls album to feature [[Carmen Electra]] before she left the group in December 2006 to pursue a solo career. == Background and production == ==Recording== ==Title and artwork== ==Composition== ===Music and lyrics=== ===Songs and lyrical content=== == Release and promotion == == Singles == ===Promotional singles=== == Track listing == {{Track listing | headline = Standard edition<ref name = "Album booklet">{{cite AV media notes |title = 7/24 |year = 2006 |type = booklet |publisher = [[Syco Music|Syco]]}}</ref> | extra_column = Producer(s) | total_length = | title_width = 30% | writing_width = 70% | title1 = [[Satisfied (Backstreet Girls song)|Satisfied]] | writer1 = {{hlist|[[Pink (singer)|Alecia Moore]]|[[Rhett Lawrence]]|[[Jimmy Harry]]}} | extra1 = {{hlist|[[Jimmy Harry]]|[[Rhett Lawrence]]|[[Siobhan Fahey]]{{ref|a|[a]}}}} | length1 = | title2 = [[Irresistible (Backstreet Girls song)|Irresistible]] | note2 = featuring [[Elephant Man]] | writer2 = {{hlist|Eric Seats|[[Tweet (singer)|Clarlene Keys]]|[[Elephant Man|O'Neil Bryan]]|[[Timbaland & Magoo|Melvin Barcliff]]|Rapture Stewart|Hannon Lane}} | extra2 = {{hlist|Eric Seats|Rapture Stewart|[[Mary Brown (songwriter)|Mary Brown]]{{ref|a|[a]}}}} | length2 = | title3 = [[Models (Backstreet Girls song)|Models]] | writer3 = {{hlist|Moore|Lawrence|Harry}} | extra3 = {{hlist|Harry|Fahey{{ref|a|[a]}}}} | length3 = | title4 = [[Candy (Backstreet Girls song)|Candy]] | writer4 = {{hlist|[[Jimmy Jam and Terry Lewis|James Harris III]]|[[Jimmy Jam and Terry Lewis|Terry Lewis]]|[[Dallas Austin]]|[[Rebbie Jackson]]|[[Debra Killings]]}} | extra4 = {{hlist|[[Jimmy Jam and Terry Lewis]]|[[Dallas Austin]]}} | length4 = | title5 = Wild Horses | writer5 = {{hlist|[[Wayne Hector]]|Barcliff|[[Soulshock|Carsten Schack]]|[[Kenneth Karlin]]|[[Louis Biancaniello]]|[[Sam Watters]]}} | extra5 = {{hlist|[[Soulshock and Karlin]]|[[Louis Biancaniello]]|[[Sam Watters]]|[[Wayne Hector]]{{ref|a|[a]}}}} | length5 = | title6 = [[All Nite (Don't Stop (song)|All Nite (Don't Stop)]] | note6 = featuring [[Sean Paul]] | writer6 = {{hlist|Harris III|Lewis|Jason Henriques|Jeremy Harding|[[Cham (singer)|Damon Beckett]]|[[Just Blaze|Justin Smith]]|[[Solange Knowles]]|[[Sean Paul|Sean Henriques]]|[[Babyface (musician)|Kenneth Edmonds]]|[[Pharrell Williams]]|[[Chad Hugo]]}} | extra6 = {{hlist|Jimmy Jam and Terry Lewis|Jeremy Harding|[[Just Blaze]]{{ref|b|[b]}}|Brown{{ref|a|[a]}}}} | length6 = | title7 = Money | writer7 = {{hlist|Harris III|Lewis|Austin|Jackson|Killings|Smith}} | extra7 = {{hlist|Jimmy Jam and Terry Lewis|Austin}} | length7 = | title8 = Watch Me Go | writer8 = {{hlist|[[Morris Day]]|[[Jesse Johnson (musician)|Jesse Johnson]]|[[Jellybean Johnson]]}} | extra8 = Jimmy Jam and Terry Lewis | length8 = | title9 = Waiting | writer9 = {{hlist|Harris III|Lewis|Moore|[[Linda Perry]]|[[Cathy Dennis]]}} | extra9 = {{hlist|Jimmy Jam and Terry Lewis|[[Linda Perry]]|Brown{{ref|a|[a]}}}} | length9 = | title10 = Release Yo' Self | note10 = featuring [[Method Man]] | writer10 = {{hlist|[[Rob Dougan]]|[[Amerie|Amerie Rogers]]|[[Street Life (rapper)|Patrick Charles]]|[[Method Man|Clifford Smith]]}} | extra10 = {{hlist|[[Rob Dougan]]|[[Jack Knight (songwriter)|Jack Knight]]{{ref|a|[a]}}}} | length10 = }} {{track listing | headline = Deluxe edition | extra_column = Producer(s) | total_length = | title_width = 30% | writing_width = 70% | title11 = Swinging London Town | writer11 = {{hlist|[[Manuel Seal]]|[[Solange Knowles]][[Robert Waller (musician)|Robert Waller]]}} | extra11 = {{hlist|[[Manuel Seal]]|[[Solange Knowles]]{{ref|a|[a]}}|[[Robert Waller (musician)|Robert Waller]]{{ref|a|[a]}}|[[Karen Poole]]{{ref|a|[a]}}}} | length11 = | title12 = It's Magic | writer12 = [[Mary Brown (songwriter)|Mary Brown]] | extra12 = {{hlist|Malik Pendleton|Brown{{ref|a|[a]}}}} | length12 = }} ==Notes== * <sup>{{note|a|[a]}}</sup> signifies a vocal producer. * <sup>{{note|b|[b]}}</sup> signifies an additional producer. ===Sample credits=== * "All Nite (Don't Stop)" contains a portion of the composition "[[There She Goes (Babyface song)|There She Goes]]", written by [[Babyface (musician)|Kenneth Edmonds]], [[Pharrell Williams]] and [[Chad Hugo]]. == Personnel == == Charts == === Weekly charts === === Year-end charts === == Certifications and sales == ==Notes== {{reflist|group=note}} == References == {{Reflist}} {{Backstreet Girls (girl group)|state=collapsed}} {{Authority control}} {{DEFAULTSORT:7 24}} [[Category:2006 albums]] [[Category:Backstreet Girls (girl group) albums]] [[Category:Columbia Records albums]] [[Category:Tropical house albums]] [[Category:House music albums by American artists]] [[Category:Contemporary R&B albums by American artists]] 0ubcs8kdklxve8ijkn7gzbtwtzupwpu 769822 769821 2026-10-23T01:27:30Z ~2026-56530-26 76376 /* Track listing */ 769822 wikitext text/x-wiki {{short description|2006 studio album by Backstreet Girls}} {{about|the Backstreet Girls album|the date|July 24|other uses|724 (disambiguation)}} {{good article}} {{Use mdy dates|date=September 2019}} {{Infobox album | name = 7/24 | type = studio | artist = [[Backstreet Girls (girl group)|Backstreet Girls]] | cover = | border = | alt = | caption = | released = {{start date|2006|05|27}} | recorded = September–December 2005 | venue = | studio = | genre = {{flatlist| * [[Pop music|Pop]] * [[tropical house]] * [[comedy pop]] * [[Contemporary R&B|R&B]] }} | length = | label = {{flatlist| * [[Columbia Records|Columbia]] * [[Syco Music|Syco]] }} | producer = {{flatlist| * [[Rob Dougan]] * [[Rhett Lawrence]] * [[Manuel Seal]] * Eric Seats * Jeremy Harding * [[Linda Perry]] * Malik Pendleton * Rapture Stewart * [[Dallas Austin]] * [[Jimmy Harry]] * [[Soulshock and Karlin]] * [[Just Blaze]] * [[Jimmy Jam and Terry Lewis]] }} | prev_title = [[Reflective (Backstreet Girls album)|Reflective]] | prev_year = 2005 | next_title = [[Backstreet Girls (album)|Backstreet Girls]] | next_year = 2007 | misc = {{Singles | name = 7/24 | type = Studio | single1 = [[Irresistible (Backstreet Girls song)|Irresistible]] | single1date = February 26, 2006 | single2 = [[All Nite (Don't Stop) (song)|All Nite (Don't Stop)]] | single2date = May 31, 2006 | single3 = [[Satisfied (Backstreet Girls song)|Satisfied]] | single3date = September 27, 2006 }} }} '''''7/24''''' is the second studio album by American comedy girl group [[Backstreet Girls (girl group)|Backstreet Girls]], released by [[Syco Music]] and [[Columbia Records]] on May 27, 2006. The record is the follow-up to the group's debut studio album ''[[Reflective (Backstreet Girls album)|Reflective]]'' (2005). Its lyrics discuss themes of [[female empowerment]] and love. It features guest appearances by American [[dancehall]] and [[hip hop]] artists [[Elephant Man]], [[Sean Paul]] and [[Method Man]], and collaborations with [[Record producer|producers]] [[Manuel Seal]], [[Dallas Austin]] and [[Jimmy Jam and Terry Lewis]]. ''7/24'' is primarily a [[Pop music|pop]], [[tropical house]] and [[Contemporary R&B|R&B]] record that includes elements of [[reggae]], [[funk]], [[electronic dance music]], [[hip hop]] and [[Trap music (EDM)|trap]]. Unlike the genres explored on ''Reflective'', ''7/24''{{'s}} songs incorporate new genres like tropical house. This is the first Backstreet Girls album to feature [[Carmen Electra]] before she left the group in December 2006 to pursue a solo career. == Background and production == ==Recording== ==Title and artwork== ==Composition== ===Music and lyrics=== ===Songs and lyrical content=== == Release and promotion == == Singles == ===Promotional singles=== == Track listing == {{Track listing | headline = Standard edition<ref name = "Album booklet">{{cite AV media notes |title = 7/24 |year = 2006 |type = booklet |publisher = [[Syco Music|Syco]]}}</ref> | extra_column = Producer(s) | total_length = | title_width = 30% | writing_width = 70% | title1 = [[Satisfied (Backstreet Girls song)|Satisfied]] | writer1 = {{hlist|[[Pink (singer)|Alecia Moore]]|[[Rhett Lawrence]]|[[Jimmy Harry]]}} | extra1 = {{hlist|[[Jimmy Harry]]|[[Rhett Lawrence]]|[[Siobhan Fahey]]{{ref|a|[a]}}}} | length1 = | title2 = [[Irresistible (Backstreet Girls song)|Irresistible]] | note2 = featuring [[Elephant Man]] | writer2 = {{hlist|Eric Seats|[[Tweet (singer)|Clarlene Keys]]|[[Elephant Man|O'Neil Bryan]]|[[Timbaland & Magoo|Melvin Barcliff]]|Rapture Stewart|Hannon Lane}} | extra2 = {{hlist|Eric Seats|Rapture Stewart|[[Mary Brown (songwriter)|Mary Brown]]{{ref|a|[a]}}}} | length2 = | title3 = [[Models (Backstreet Girls song)|Models]] | writer3 = {{hlist|Moore|Lawrence|Harry}} | extra3 = {{hlist|Harry|Fahey{{ref|a|[a]}}}} | length3 = | title4 = [[Candy (Backstreet Girls song)|Candy]] | writer4 = {{hlist|[[Jimmy Jam and Terry Lewis|James Harris III]]|[[Jimmy Jam and Terry Lewis|Terry Lewis]]|[[Dallas Austin]]|[[Rebbie Jackson]]|[[Debra Killings]]}} | extra4 = {{hlist|[[Jimmy Jam and Terry Lewis]]|[[Dallas Austin]]}} | length4 = | title5 = Wild Horses | writer5 = {{hlist|[[Wayne Hector]]|Barcliff|[[Soulshock|Carsten Schack]]|[[Kenneth Karlin]]|[[Louis Biancaniello]]|[[Sam Watters]]}} | extra5 = {{hlist|[[Soulshock and Karlin]]|[[Louis Biancaniello]]|[[Sam Watters]]|[[Wayne Hector]]{{ref|a|[a]}}}} | length5 = | title6 = [[All Nite (Don't Stop (song)|All Nite (Don't Stop)]] | note6 = featuring [[Sean Paul]] | writer6 = {{hlist|Harris III|Lewis|Jason Henriques|Jeremy Harding|[[Cham (singer)|Damon Beckett]]|[[Just Blaze|Justin Smith]]|[[Solange Knowles]]|[[Sean Paul|Sean Henriques]]|[[Babyface (musician)|Kenneth Edmonds]]|[[Pharrell Williams]]|[[Chad Hugo]]}} | extra6 = {{hlist|Jimmy Jam and Terry Lewis|Jeremy Harding|[[Just Blaze]]{{ref|b|[b]}}|Brown{{ref|a|[a]}}}} | length6 = | title7 = Money | writer7 = {{hlist|Harris III|Lewis|Austin|Jackson|Killings|Smith}} | extra7 = {{hlist|Jimmy Jam and Terry Lewis|Austin}} | length7 = | title8 = Watch Me Go | writer8 = {{hlist|[[Morris Day]]|[[Jesse Johnson (musician)|Jesse Johnson]]|[[Jellybean Johnson]]}} | extra8 = Jimmy Jam and Terry Lewis | length8 = | title9 = Waiting | writer9 = {{hlist|Harris III|Lewis|Moore|[[Linda Perry]]|[[Cathy Dennis]]}} | extra9 = {{hlist|Jimmy Jam and Terry Lewis|[[Linda Perry]]|Brown{{ref|a|[a]}}}} | length9 = | title10 = Release Yo' Self | note10 = featuring [[Method Man]] | writer10 = {{hlist|[[Rob Dougan]]|[[Amerie|Amerie Rogers]]|[[Street Life (rapper)|Patrick Charles]]|[[Method Man|Clifford Smith]]}} | extra10 = {{hlist|[[Rob Dougan]]|[[Jack Knight (songwriter)|Jack Knight]]{{ref|a|[a]}}}} | length10 = }} {{track listing | headline = Deluxe edition | extra_column = Producer(s) | total_length = | title_width = 30% | writing_width = 70% | title11 = Swinging London Town | writer11 = {{hlist|[[Manuel Seal]]|[[Solange Knowles]]|[[Robert Waller (musician)|Robert Waller]]}} | extra11 = {{hlist|[[Manuel Seal]]|[[Solange Knowles]]{{ref|a|[a]}}|[[Robert Waller (musician)|Robert Waller]]{{ref|a|[a]}}|[[Karen Poole]]{{ref|a|[a]}}}} | length11 = | title12 = It's Magic | writer12 = [[Mary Brown (songwriter)|Mary Brown]] | extra12 = {{hlist|Malik Pendleton|Brown{{ref|a|[a]}}}} | length12 = }} ==Notes== * <sup>{{note|a|[a]}}</sup> signifies a vocal producer. * <sup>{{note|b|[b]}}</sup> signifies an additional producer. ===Sample credits=== * "All Nite (Don't Stop)" contains a portion of the composition "[[There She Goes (Babyface song)|There She Goes]]", written by [[Babyface (musician)|Kenneth Edmonds]], [[Pharrell Williams]] and [[Chad Hugo]]. == Personnel == == Charts == === Weekly charts === === Year-end charts === == Certifications and sales == ==Notes== {{reflist|group=note}} == References == {{Reflist}} {{Backstreet Girls (girl group)|state=collapsed}} {{Authority control}} {{DEFAULTSORT:7 24}} [[Category:2006 albums]] [[Category:Backstreet Girls (girl group) albums]] [[Category:Columbia Records albums]] [[Category:Tropical house albums]] [[Category:House music albums by American artists]] [[Category:Contemporary R&B albums by American artists]] 3ah0agllfsjy1poo1l0kwr3led0gu9q Wikipedia:AI Noticeboard/DVRTed 4 178667 769823 763500 2026-10-23T05:41:35Z DVRTed 55993 769823 wikitext text/x-wiki {{AINB case banner}} ==Discussion== {{userlinks|Wikipedia:AI Noticeboard/DVRTed}} {{AIC status|cleanup_status=requested|tracking_subpage=2026-09-13 DVRTed}} please [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 00:53, 21 September 2026 (UTC) ==Tracking table== evdea5cpxkvt9jew06l0vmjvy2y6cah 769824 769823 2026-10-23T05:43:19Z DVRTed 55993 769824 wikitext text/x-wiki {{AINB case banner |cleanup=ongoing |llmprod=ongoing |conduct=siteblock |case_name=DVRTed |original_file_date=26 August 2026 |case_type=user}} ==Discussion== {{userlinks|Wikipedia:AI Noticeboard/DVRTed}} {{AIC status|cleanup_status=requested|tracking_subpage=2026-09-13 DVRTed}} please [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 00:53, 21 September 2026 (UTC) ==Tracking table== d4t3jz4rr3wi0h10jhcafkyvgugwukz Wikipedia:AI noticeboard/DVRTed 4 178751 769825 768212 2026-10-23T05:49:06Z DVRTed 55993 769825 wikitext text/x-wiki {{AINB case banner |cleanup=analysis |llmprod= |conduct= |case_type=}} == Discussion == All around me are familiar faces... [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) == Cleanup == {{InfoCard|content='''Tracker detail''' * User: {{User-ainb|1=DVRTed}} * Start date: 2022-12-01 * End date: 2026-10-12}} === Tracking list === {{AIC article list| {{AIC article row|article=BS Nymph|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} }} p13tqq4cs7zycrswblp6alqnv2so0zc 769826 769825 2026-10-23T05:49:22Z DVRTed 55993 /* Discussion */ Reply 769826 wikitext text/x-wiki {{AINB case banner |cleanup=analysis |llmprod= |conduct= |case_type=}} == Discussion == All around me are familiar faces... [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) :test reply breaking the script [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) == Cleanup == {{InfoCard|content='''Tracker detail''' * User: {{User-ainb|1=DVRTed}} * Start date: 2022-12-01 * End date: 2026-10-12}} === Tracking list === {{AIC article list| {{AIC article row|article=BS Nymph|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} }} e81mkcen6ovehtkyfx81ngdy1swo1lv 769827 769826 2026-10-23T05:49:42Z DVRTed 55993 /* Discussion */ Reply 769827 wikitext text/x-wiki {{AINB case banner |cleanup=analysis |llmprod= |conduct= |case_type=}} == Discussion == All around me are familiar faces... [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) :test reply breaking the script [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) ::test again [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) == Cleanup == {{InfoCard|content='''Tracker detail''' * User: {{User-ainb|1=DVRTed}} * Start date: 2022-12-01 * End date: 2026-10-12}} === Tracking list === {{AIC article list| {{AIC article row|article=BS Nymph|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} }} mn0no53hpkjpn26h8oc14ejvbh7295e 769828 769827 2026-10-23T05:50:01Z DVRTed 55993 /* Discussion */ Reply 769828 wikitext text/x-wiki {{AINB case banner |cleanup=analysis |llmprod= |conduct= |case_type=}} == Discussion == All around me are familiar faces... [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) :test reply breaking the script [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) ::test again [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) :::test3 [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:50, 23 October 2026 (UTC) == Cleanup == {{InfoCard|content='''Tracker detail''' * User: {{User-ainb|1=DVRTed}} * Start date: 2022-12-01 * End date: 2026-10-12}} === Tracking list === {{AIC article list| {{AIC article row|article=BS Nymph|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} }} p1ofi3725sr0ucf3mkpm5lb8gp25sjm 769829 769828 2026-10-23T05:50:35Z DVRTed 55993 /* Tracking list */ 769829 wikitext text/x-wiki {{AINB case banner |cleanup=analysis |llmprod= |conduct= |case_type=}} == Discussion == All around me are familiar faces... [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) :test reply breaking the script [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) ::test again [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) :::test3 [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:50, 23 October 2026 (UTC) == Cleanup == {{InfoCard|content='''Tracker detail''' * User: {{User-ainb|1=DVRTed}} * Start date: 2022-12-01 * End date: 2026-10-12}} === Tracking list === {{AIC article list| {{AIC article row|article=BS Nymph|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 2|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 3|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 4|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 5|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 6|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 7|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 8|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} }} 8c2ld8sagqa676yhha6505znhldarg1 769830 769829 2026-10-23T05:50:43Z DVRTed 55993 Updated row for [[BS Nymph 4]] (using [[User:DVRTed/AINB-helper|AINB-helper]]) 769830 wikitext text/x-wiki {{AINB case banner |cleanup=analysis |llmprod= |conduct= |case_type=}} == Discussion == All around me are familiar faces... [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) :test reply breaking the script [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) ::test again [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) :::test3 [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:50, 23 October 2026 (UTC) == Cleanup == {{InfoCard|content='''Tracker detail''' * User: {{User-ainb|1=DVRTed}} * Start date: 2022-12-01 * End date: 2026-10-12}} === Tracking list === {{AIC article list| {{AIC article row|article=BS Nymph|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 2|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 3|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 4|status=tagged|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 5|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 6|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 7|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 8|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} }} smbixrvx5m7z4shv9vw5dq15hgtt4p9 769831 769830 2026-10-23T05:50:50Z DVRTed 55993 Updated row for [[BS Nymph 3]] (using [[User:DVRTed/AINB-helper|AINB-helper]]) 769831 wikitext text/x-wiki {{AINB case banner |cleanup=analysis |llmprod= |conduct= |case_type=}} == Discussion == All around me are familiar faces... [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) :test reply breaking the script [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) ::test again [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:49, 23 October 2026 (UTC) :::test3 [[User:DVRTed|DVRTed]] ([[User talk:DVRTed|talk]]) 05:50, 23 October 2026 (UTC) == Cleanup == {{InfoCard|content='''Tracker detail''' * User: {{User-ainb|1=DVRTed}} * Start date: 2022-12-01 * End date: 2026-10-12}} === Tracking list === {{AIC article list| {{AIC article row|article=BS Nymph|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 2|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 3|status=ongoing|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 4|status=tagged|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 5|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 6|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 7|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} {{AIC article row|article=BS Nymph 8|status=completed|notes=2 edits: [[Special:Diff/765391|(+5)]] [[Special:Diff/762815|(+330)]]}} }} rxqlwqm06o238uwmd1yxjd913hvrnth MediaWiki:AI-noticeboard.js 8 178767 769794 768216 2026-10-22T20:03:01Z Chaotic Enby 58843 🚰 769794 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ (async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl('Wikipedia:AI noticeboard/' + wizard.title, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { console.log(json); var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); console.log(preloadQueryIndex); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; console.log(targetPage); if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; console.log(wizard); return; } } constructUI(); })(); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ 7bfep6ho8m5euyqb9xw99kd9bk0c8ao 769796 769794 2026-10-22T20:18:17Z Chaotic Enby 58843 wuh 769796 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ (async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPage = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); if (userGroups.includes('autoconfirmed') || userGroups.includes('confirmed') || userGroups.includes('extendedconfirmed') || userGroups.includes('sysop')) { targetPage = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPage, "rvprop": "content", "rvslots": "main" }); var filingList = filingListQuery.query.pages[0].targetPage.revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n =' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPage, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { console.log(json); var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); console.log(preloadQueryIndex); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; console.log(targetPage); if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; console.log(wizard); return; } } constructUI(); })(); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ tenuju1w8ulx81juj4thyyz966a8kzt 769799 769796 2026-10-22T20:29:14Z Chaotic Enby 58843 769799 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ (async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; const NAC_LISTING_ID = (mw.config.get('wgServerName') == 'test.wikipedia.org' ? 179449 : 84562970); var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPage = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); if (userGroups.includes('autoconfirmed') || userGroups.includes('confirmed') || userGroups.includes('extendedconfirmed') || userGroups.includes('sysop')) { targetPage = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPage, "rvprop": "content", "rvslots": "main" }); var filingList = filingListQuery.query.pages[NAC_LISTING_ID].targetPage.revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n =' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPage, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { console.log(json); var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); console.log(preloadQueryIndex); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; console.log(targetPage); if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; console.log(wizard); return; } } constructUI(); })(); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ rq6tp20c63cbnch11wdgqr1qnt5r3pq 769800 769799 2026-10-22T20:30:49Z Chaotic Enby 58843 769800 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ (async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; const NAC_LISTING_ID = (mw.config.get('wgServerName') == 'test.wikipedia.org' ? 179449 : 84562970); var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPage = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); if (userGroups.includes('autoconfirmed') || userGroups.includes('confirmed') || userGroups.includes('extendedconfirmed') || userGroups.includes('sysop')) { targetPage = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPage, "rvprop": "content", "rvslots": "main" }); console.log(filingListQuery.query.pages); var filingList = filingListQuery.query.pages[NAC_LISTING_ID].targetPage.revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n =' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPage, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { console.log(json); var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); console.log(preloadQueryIndex); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; console.log(targetPage); if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; console.log(wizard); return; } } constructUI(); })(); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ bhyl12rwtblqx7blhee84cwjlqc4ji3 769801 769800 2026-10-22T20:31:31Z Chaotic Enby 58843 well that's simpler 769801 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ (async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPage = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); if (userGroups.includes('autoconfirmed') || userGroups.includes('confirmed') || userGroups.includes('extendedconfirmed') || userGroups.includes('sysop')) { targetPage = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPage, "rvprop": "content", "rvslots": "main" }); console.log(filingListQuery.query.pages); var filingList = filingListQuery.query.pages[0].targetPage.revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n =' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPage, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { console.log(json); var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); console.log(preloadQueryIndex); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; console.log(targetPage); if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; console.log(wizard); return; } } constructUI(); })(); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ k40q8rcyhwndaiznccnzz2adoeqitcu 769802 769801 2026-10-22T20:32:16Z Chaotic Enby 58843 769802 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ (async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPage = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); if (userGroups.includes('autoconfirmed') || userGroups.includes('confirmed') || userGroups.includes('extendedconfirmed') || userGroups.includes('sysop')) { targetPage = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPage, "rvprop": "content", "rvslots": "main" }); console.log(filingListQuery.query.pages[0]); var filingList = filingListQuery.query.pages[0].revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n =' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPage, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { console.log(json); var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); console.log(preloadQueryIndex); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; console.log(targetPage); if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; console.log(wizard); return; } } constructUI(); })(); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ 0ctzm5zmxk9jjvm6ajgaahj2xdax9o6 769803 769802 2026-10-22T20:32:58Z Chaotic Enby 58843 disambig 769803 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ (async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPageTitle = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); if (userGroups.includes('autoconfirmed') || userGroups.includes('confirmed') || userGroups.includes('extendedconfirmed') || userGroups.includes('sysop')) { targetPageTitle = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPageTitle, "rvprop": "content", "rvslots": "main" }); console.log(filingListQuery.query.pages[0]); var filingList = filingListQuery.query.pages[0].revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n =' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPageTitle, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { console.log(json); var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); console.log(preloadQueryIndex); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; console.log(targetPage); if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; console.log(wizard); return; } } constructUI(); })(); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ 3wkvvb9s269jkjy4vrz7pd8wc1bae8r 769804 769803 2026-10-22T20:33:32Z Chaotic Enby 58843 no spacing needed 769804 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ (async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPageTitle = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); if (userGroups.includes('autoconfirmed') || userGroups.includes('confirmed') || userGroups.includes('extendedconfirmed') || userGroups.includes('sysop')) { targetPageTitle = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPageTitle, "rvprop": "content", "rvslots": "main" }); console.log(filingListQuery.query.pages[0]); var filingList = filingListQuery.query.pages[0].revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n=' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPageTitle, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { console.log(json); var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); console.log(preloadQueryIndex); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; console.log(targetPage); if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; console.log(wizard); return; } } constructUI(); })(); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ c79pdqqeymond2jbsd4vm3099comj5m 769806 769804 2026-10-22T20:42:23Z Chaotic Enby 58843 769806 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ mw.loader.using( [ 'mediawiki.user' ] ).then( async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPageTitle = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); if (userGroups.includes('autoconfirmed') || userGroups.includes('confirmed') || userGroups.includes('extendedconfirmed') || userGroups.includes('sysop')) { targetPageTitle = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPageTitle, "rvprop": "content", "rvslots": "main" }); var filingList = filingListQuery.query.pages[0].revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n=' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPageTitle, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; return; } } constructUI(); }); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ ilitx42a0ff4zyaq039pqcp60l5dtgi 769807 769806 2026-10-22T20:44:17Z Chaotic Enby 58843 769807 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ mw.loader.using( [ 'mediawiki.user' ] ).then( async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPageTitle = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); console.log(userGroups); if (userGroups.includes('autoconfirmed') || userGroups.includes('confirmed') || userGroups.includes('extendedconfirmed') || userGroups.includes('sysop')) { targetPageTitle = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPageTitle, "rvprop": "content", "rvslots": "main" }); var filingList = filingListQuery.query.pages[0].revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n=' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPageTitle, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; return; } } constructUI(); }); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ teou5x0nhxz7xus82k1uqbl14b5kqpz 769808 769807 2026-10-22T20:46:05Z Chaotic Enby 58843 brain moment 769808 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ mw.loader.using( [ 'mediawiki.user' ] ).then( async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPageTitle = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); if (!userGroups.includes('autoconfirmed') && !userGroups.includes('confirmed') && !userGroups.includes('extendedconfirmed') && !userGroups.includes('sysop')) { targetPageTitle = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPageTitle, "rvprop": "content", "rvslots": "main" }); var filingList = filingListQuery.query.pages[0].revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n=' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPageTitle, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; return; } } constructUI(); }); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ 8pb6q5z1nxx2kvkmujz7u22hixeqv0t 769809 769808 2026-10-22T20:48:09Z Chaotic Enby 58843 debug 769809 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ mw.loader.using( [ 'mediawiki.user' ] ).then( async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPageTitle = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); console.log(userGroups); if (!userGroups.includes('autoconfirmed') && !userGroups.includes('confirmed') && !userGroups.includes('extendedconfirmed') && !userGroups.includes('sysop')) { targetPageTitle = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPageTitle, "rvprop": "content", "rvslots": "main" }); var filingList = filingListQuery.query.pages[0].revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n=' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } break; // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPageTitle, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; return; } } constructUI(); }); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ 97zfc83abxix51aw9ylxvta0j2d5zan 769810 769809 2026-10-22T20:48:43Z Chaotic Enby 58843 769810 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ mw.loader.using( [ 'mediawiki.user' ] ).then( async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPageTitle = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); console.log(userGroups); if (!userGroups.includes('autoconfirmed') && !userGroups.includes('confirmed') && !userGroups.includes('extendedconfirmed') && !userGroups.includes('sysop')) { targetPageTitle = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPageTitle, "rvprop": "content", "rvslots": "main" }); var filingList = filingListQuery.query.pages[0].revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n=' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } return; // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPageTitle, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; return; } } constructUI(); }); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ butuu2wk4ql167xir79vstrm4lxjuw5 769811 769810 2026-10-22T20:50:23Z Chaotic Enby 58843 769811 javascript text/javascript /** * MediaWiki:AI-noticeboard.js * * JavaScript used for opening AINB cases. * Used on [[Wikipedia:AI noticeboard/AINB/Filing]]. * Loaded via [[mw:Snippets/Load JS and CSS by URL]]. * * Edits can be proposed via [[Wikipedia talk:AI noticeboard]]. * * Author: [[User:Chaotic Enby]] (with elements adapted from a script by [[User:SD0001]]) * Licence: MIT (dual-licensed with CC-BY-SA 4.0 and GFDL 1.2) */ /* jshint maxerr: 999 */ /* globals mw, $, OO */ /* <nowiki> */ mw.loader.using( [ 'mediawiki.user' ] ).then( async function () { var apiOptions = { parameters: { format: 'json', formatversion: '2' }, ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:AI-noticeboard.js' } } }; var wizard = {}, ui = {}; wizard.api = new mw.Api(apiOptions); wizard.lookupApi = new mw.Api(apiOptions); async function constructUI() { ui.itemsLayout = []; ui.itemsInput = []; ui.itemsInput.push(new OO.ui.TextInputWidget({ placeholder: 'Typically a username without the "User:" prefix', maxLength: 150, })); ui.radioItems = [ new OO.ui.RadioOptionWidget( { data: 'article', label: 'Article' } ), new OO.ui.RadioOptionWidget( { data: 'user', label: 'User' } ), new OO.ui.RadioOptionWidget( { data: 'group', label: 'Group' } ), ] ui.itemsInput.push(new OO.ui.RadioSelectWidget( { items: ui.radioItems } )); ui.itemsInput[1].selectItem(ui.radioItems[1]); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[0], { label: 'Case name', align: 'top', })); ui.itemsLayout.push(new OO.ui.FieldLayout(ui.itemsInput[1], { label: 'Case type', align: 'top', })); ui.itemsLayout.push(ui.submitLayout = new OO.ui.FieldLayout(ui.submitButton = new OO.ui.ButtonWidget({ label: 'Submit', flags: [ 'progressive', 'primary' ], }))); ui.fieldset = new OO.ui.FieldsetLayout({ classes: [ 'container' ], items: ui.itemsLayout }); $('#ainb-filing-container').empty().append(ui.fieldset.$element); $('#' + ui.itemsInput[1].getElementId()).css({ 'display': 'flex', 'align-items': 'baseline', 'flex-wrap': 'wrap', 'gap': '2em' }); ui.submitButton.on('click', handleSubmit); ui.itemsInput[0].on('enter', handleSubmit); ui.itemsInput[0].moveCursorToStart(); } async function handleSubmit() { wizard.lookupApi.abort(); // abort older API requests wizard.title = ui.itemsInput[0].getValue(); wizard.type = ui.itemsInput[1].findSelectedItem().getData(); if (wizard.type === 'article') { wizard.links = '{{pagelinks|' + wizard.title + '}}\n\n'; } else if (wizard.type === 'user') { wizard.links = '{{user-ainb|' + wizard.title + '}}\n\n'; } else { wizard.links = ''; } // re-initialize await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": "Wikipedia:AI noticeboard/AINB/Blank report|Wikipedia:AI noticeboard/" + wizard.title, "rvprop": "content", "rvslots": "main" }).then(setPrefillsFromPageData); wizard.filing = '=== {{safesubst' + ':#time:j F Y}} ===\n' + '[ Replace this line with your new filing ] ~~' + '~~'; var targetPageTitle = 'Wikipedia:AI noticeboard/' + wizard.title; if (!wizard.pageExists) { // First filing wizard.pageText = wizard.preloadText.replace('$1', 'analysis') .replace('$2', 'review') .replace('$3', 'undetermined') .replaceAll('$4', wizard.title) .replace('$5', wizard.links + wizard.filing) .replace('$6', wizard.type) .replaceAll('<noinclude/>', '') .replaceAll(/<noinclude>.*?<\/noinclude>/g, ''); var userGroups = await mw.user.getGroups(); if (!userGroups.includes('autoconfirmed') && !userGroups.includes('confirmed') && !userGroups.includes('extendedconfirmed') && !userGroups.includes('sysop')) { targetPageTitle = 'Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports'; var filingListQuery = await wizard.lookupApi.get({ "action": "query", "prop": "revisions|description|info", "titles": targetPageTitle, "rvprop": "content", "rvslots": "main" }); var filingList = filingListQuery.query.pages[0].revisions[0].slots.main.content; wizard.pageText = filingList + '\n\n=' + wizard.title + '=\n' + wizard.pageText; } } else { // Repeat filing wizard.pageText = wizard.pageText.replace('== Cleanup ==', wizard.filing + '\n\n' + '== Cleanup =='); wizard.pageText = wizard.pageText.replace(/^([^\r\n]*)\|(article|user|group)}}/, '$1|' + wizard.type + '}}') .replace(/conduct\s*=[^|]*\|\s*(cleanup|llmprod|case_name|original_file_date|case_type)/,'conduct=review|$1'); } // Here be vibecoded form shenanigans const form = $('<form>', { method: 'POST', action: mw.util.getUrl(targetPageTitle, {action: 'edit'}) }).css('display', 'none').append( $('<textarea>', { name: 'wpTextbox1', text: wizard.pageText })).append( $('<textarea>', { name: 'wpUnicodeCheck', text: 'ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ' // fancyyyy :3 })).append( $('<textarea>', { name: 'wpAntispam', text: '' })).append( $('<textarea>', { name: 'wpSection', text: '' })).append( $('<textarea>', { name: 'wpStarttime', text: '' })).append( $('<textarea>', { name: 'wpEdittime', text: '' })).append( $('<textarea>', { name: 'editRevId', text: '' })).append( $('<textarea>', { name: 'wpPreview', text: '1' })).append( $('<textarea>', { name: 'wpUltimateParam', text: '1' })); form.appendTo(document.body).trigger('submit'); // End of vibecoded part } function setPrefillsFromPageData(json) { var preloadQueryIndex = (json.query.pages[0].title === 'Wikipedia:AI noticeboard/AINB/Blank report' ? 0 : 1); wizard.preloadText = json.query.pages[preloadQueryIndex].revisions[0].slots.main.content; var targetPage = json.query.pages[1 - preloadQueryIndex]; if (!targetPage || targetPage.invalid || targetPage.missing) { wizard.pageExists = false; return; } else { wizard.pageExists = true; wizard.pageText = targetPage.revisions[0].slots.main.content; return; } } constructUI(); }); // File-level closure to protect functions from being exposed to the global scope or overwritten /* </nowiki> */ 8pb6q5z1nxx2kvkmujz7u22hixeqv0t User:Nardog/sandbox11.js 2 178772 769765 769704 2026-10-22T16:25:39Z Nardog 40946 769765 javascript text/javascript mw.hook('wikipage.diff').remove(window.sdcb); mw.hook('wikipage.diff.wikitextBodyUpdate').remove(window.sdcbu); $('.smartdiff-link').contents().unwrap().end().remove(); $(':is(.diff-addedline, .diff-addedline, .diff-context) > div, .mw-diff-inline-added, .mw-diff-inline-deleted, .mw-diff-inline-changed').contents().each(function () { if (this.previousSibling && this.previousSibling.tagName === this.tagName) { this.previousSibling.textContent += this.textContent; this.remove(); } }); window.smartdiffTemplates = [ { names: ['T', 'Tl'], namespace: 10, forceNs: true, end: 1 }, { names: ['Tlx'], namespace: 10, end: 1 }, { names: ['U'], prefix: 'Special:Contributions/', end: 1 }, { names: ['Re', 'Reply to', 'Ping'], prefix: 'Special:Contributions/' }, { names: ['About'], start: 3, skipEven: true }, { names: ['For'], start: 2 }, { names: ['Other uses', 'Otheruses'], end: 1 }, { names: ['Section link', 'Slink'], end: 1 }, { names: ['Redirect'], skipEven: true, noRedirectEnd: 1 }, { names: ['Shortcut'], noRedirectStart: 1 }, { names: ['Tracked', 'Phab'], prefix: 'phab:', end: 1 }, { names: [ 'Distinguish', 'Main', 'Main article', 'Further', 'See also', 'Seealso' ] }, { names: ['Ll'], end: 1 } ]; mw.loader.using([ 'mediawiki.util', 'mediawiki.Title', 'mediawiki.api' ], () => { mw.loader.addStyleTag(`body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external) { color: #36b; } body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external):visited { color: #636; } body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external):active { color: #b63; }`); class SmartDiff { constructor($diff) { this.now = performance.now(); this.$diff = $diff; this.isView = mw.config.get('wgNamespaceNumber') !== -1 && mw.config.get('wgAction') === 'view' && $diff.nextAll().is('.diff-hr'); [ ['old', '#mw-diff-otitle1 a, #differences-prevlink'], ['new', '#mw-diff-ntitle1 a, #differences-nextlink'] ].forEach(([side, selector]) => { let link = this.$diff[0].querySelector(selector); let pn = link && mw.util.getParamValue('title', link.search); if (pn) { this[side] = { pn, ns: mw.Title.newFromText(pn).getNamespaceId() }; } }); this.isSamePage = this.old?.pn === this.new?.pn; this.titles = {}; this.noRedirLinks = new WeakSet(); SmartDiff.sds.set($diff[0], this); this.init(); } async init($rows = this.$diff) { this.side = 'old'; for (let div of $rows.find( '.diff-deletedline > div, .mw-diff-inline-deleted' )) { await this.processLine(div); } this.side = 'new'; for (let div of $rows.find( '.diff-addedline > div, .mw-diff-inline-added, .mw-diff-inline-context' )) { await this.processLine(div); } for (let div of $rows.find( '.mw-diff-inline-changed, .mw-diff-inline-moved' )) { await this.processLine(div, true); } let $contexts = $rows.find('.diff-context > div'), clones = []; for (let [i, div] of $contexts.get().entries()) { if (i % 2) { this.side = 'new'; if (this.divHasLink) { if (this.sidePropUsed) { await this.processLine(div); } else { div.replaceChildren( ...$contexts.eq(i - 1).contents().clone() ); clones.push(div); } } } else { this.side = 'old'; await this.processLine(div); } } $(clones).find('.smartdiff-link[title]').each((_, link) => { this.titles[link.title]?.links.push(link); }); this.queryTitles(); if (this.hasError) { mw.notify('SmartDiff error', { type: 'warn' }); } console.log(performance.now() - this.now); } async processLine(div, isInlineChange) { this.divHasLink = false; this.sidePropUsed = false; if (div.querySelector('a[href]')) return; let tokens; if (isInlineChange) { tokens = this.tokenize( div, 'del, .mw-diff-movedpara-left, .mw-diff-movedpara-right' ); this.side = 'new'; await this.exec(tokens); this.escapeTags(tokens, 'ins'); this.unescapeTags(tokens, 'del'); this.side = 'old'; await this.exec(tokens, true); this.unescapeTags(tokens); } else { tokens = this.tokenize(div); await this.exec(tokens); } if (!this.divHasLink) return; try { let newDiv = this.unescape(tokens); this.verify(div, newDiv); div.replaceChildren(...newDiv.childNodes); } catch (e) { debugger; if (typeof e === 'string') { this.hasError = true; console.warn(`SmartDiff error: ${e}`); } else { throw e; } } } tokenize(el, escSelector) { return [...el.childNodes].flatMap(node => { if (node.nodeType === 3) { return node.textContent.split('').map(s => ({ s })); } if (node.nodeType !== 1) { return []; } if (escSelector && node.matches(escSelector)) { return [ { openingTag: node }, { esc: this.tokenize(node, escSelector), tag: node }, { closingTag: node } ]; } return [ { openingTag: node }, ...this.tokenize(node, escSelector), { closingTag: node } ]; }); } escapeTags(tokens, selector) { let openTags = [], data = []; tokens.forEach((token, i) => { if (token.openingTag?.matches(selector)) { openTags.push([token.openingTag, i + 1]); } else if (token.closingTag && openTags.length && token.closingTag.tagName === openTags.at(-1)[0].tagName ) { data.push([...openTags.pop(), i]); } }); data.reverse().forEach(([tag, start, end]) => { let token = { tag }; token.esc = tokens.splice(start, end - start, token); }); } unescapeTags(tokens, selector) { tokens.splice(0, Infinity, ...tokens.flatMap(token => ( token.esc && (!selector || token.tag.matches(selector)) ? token.esc : [token] ))); } unescape(tokens) { let els = [$('<div>')[0]], lastText = ''; tokens.forEach(token => { if (token.openingTag) { if (lastText) { els.at(-1).append(lastText); lastText = ''; } let el = token.openingTag; if (!token.link) { el = el.cloneNode(); } els.at(-1).append(el); els.push(el); } else if (token.closingTag) { let el = els.pop(); if (!els.length) { throw `too many closing tags.\n\n${el.innerHTML}`; } if (el.tagName !== token.closingTag.tagName) { throw `expected </${ token.closingTag.tagName }>, got </${el.tagName}>.\n\n${els[0].innerHTML}`; } if (lastText) { el.append(lastText); lastText = ''; } } else { lastText += token.s; } }); if (lastText) { els.at(-1).append(lastText); } if (els.length !== 1) { throw `too many opening tags.\n\n${els[0].innerHTML}`; } return els[0]; } verify(div, newDiv) { let origHtml = div.innerHTML; let $comp = $(newDiv).clone(); $comp.find('.smartdiff-link').contents().unwrap(); let comp = $comp.html().replace(/<\/(ins|del)><\1(?: [^>]+)?>/g, ''); if (comp !== origHtml) { throw `changed substance.\n\nOriginal:\n${origHtml}\n\nCleaned:\n${comp}\n\nFull:\n${newDiv.innerHTML}`; } let emptyCells = newDiv.querySelectorAll(':is(ins, del):empty'); if (emptyCells.length) { console.log('Empty cells found:', ...emptyCells); mw.notify('Empty cells found'); } } async exec(tokens, isSecond) { let s = tokens.map(token => token.s || '').join(''); let modes = isSecond ? ['url', 'link', 'template', 'gallery'] : ['url', 'link', 'template', 'heading', 'gallery']; for (let mode of modes) { await this.search(s, tokens, mode); } } async search(s, tokens, mode, data) { for (let match of s.matchAll(SmartDiff[mode + 'Re'])) { await this[mode + 'Callback']( tokens, ...match.indices.slice(1).map((indices, i) => indices && { s: match[i + 1], indices, tokens, tokenIndices: SmartDiff.tokenIndices }), data ); } } static tokenIndices() { let count = 0, start; for (let [i, token] of this.tokens.entries()) { if (token.s) { if (count === this.indices[0]) { start = i; } if (count === this.indices[1] - 1) { return [start, i + 1]; } count++; } } } static linkRe = /\[\[\s*(?:<tvar(?: [^>]*)?>\s*)?((?:[^<>\[\]{|}])+?)(?:\s*<\/tvar>|\{\{#translation:\s*\}\})?\s*(?:\||\]\])/dg; async linkCallback(tokens, mid) { let s = this.decodeWikitext(mid.s, true); let t; if (s.startsWith('/')) { t = await this.getSubpage(s); } else if (s.startsWith('#') && (!this.isView || !this.isSamePage)) { t = mw.Title.newFromText(this.getProp() + s); } else if (s.startsWith('../')) { t = await this.getParentPage(s); } else { t = mw.Title.newFromText(s); } if (!t) return; this.link(tokens, ...mid.tokenIndices(), t); } static templateRe = /((?<!{){{\s*(?:(?:#invoke|(?:safe)?subst|msg(?:nw)?|raw|int):\s*)?(?:<tvar(?: [^>]*)?>\s*)?)([^<>\[\]{|}]+?)((?:\s*<\/tvar>)?\s*(\|.*)?(?:}}|$))/dg; async templateCallback(tokens, pre, mid, post, args) { let s = this.decodeWikitext(mid.s, true); let t; if (pre.s.includes('invoke')) { t = mw.Title.makeTitle(828, s); } else if (s.startsWith('#')) { return; } else if (pre.s.includes('int')) { t = mw.Title.makeTitle(8, s); } else if (s.startsWith('/')) { t = await this.getSubpage(s, 10); } else if (s.startsWith('../')) { t = await this.getParentPage(s, 10); } else { if (!pre.s.includes('msg') && !pre.s.includes('raw')) { let match = s.match(/^[^:]+(?::(?=.)|$)/); if (match && SmartDiff.magicWords.includes(match[0])) return; } t = mw.Title.newFromText(s, 10); } if (t) { this.link(tokens, ...mid.tokenIndices(), t); } if (!args) return; let [postStart, postEnd] = post.tokenIndices(); let newPost = tokens.slice(postStart, postEnd); await this.search(post.s, newPost, 'template'); if (!t || !SmartDiff.templates) return; let name = t.getMainText(); for (let data of SmartDiff.templates) { if (Array.isArray(data?.names) && Array.prototype.includes.call(data.names, name) ) { await this.search( post.s, newPost, 'templateArgs', { ...data, i: 1 } ); } } tokens.splice(postStart, postEnd - postStart, ...newPost); } static templateArgsRe = /\|\s*(?:([^=|]*?)\s*=)?\s*(?:<tvar(?: [^>]*)?>\s*)?(.*?)(?:\s*<\/tvar>)?\s*(?=\||{{!}}|}}|$)/dg; templateArgsCallback(tokens, name, mid, data) { let n = name ? Number(name.s) || name.s : data.i++; if (typeof n !== 'number' || ( n < data.start || n > data.end || (n % 2 ? data.skipOdd : data.skipEven) )) { return; } if (!mid.s) return; let s = this.decodeWikitext(mid.s); if (data.prefix) { s = data.prefix + s; } if (data.suffix) { s += data.suffix; } let t = data.forceNs ? mw.Title.makeTitle(data.namespace, s) : mw.Title.newFromText(s, data.namespace); if (!t) return; this.link( tokens, ...mid.tokenIndices(), t, n >= data.noRedirectStart || n <= data.noRedirectEnd ); } static urlRe = /(\[(?=.+\]))?((?:\bhttps?:)?\/\/[^\s"<>\[\]{|}]*)([^\s"<>\[\]{|}])/dg; urlCallback(tokens, pre, mid, last) { let omitLast; if (!pre) { if (mid.s.startsWith('//')) return; if (last.s === ';') { let match = mid.s.match(/&#?[\da-z]+$/i); let source = match && match[0] + last.s; omitLast = !match || this.decodeWikitext(source) === source; } else { omitLast = '!,.:?'.includes(last.s) || last.s === ')' && mid.s.includes('('); } } let s = mid.s; if (!omitLast) { s += last.s; } let [midStart, midEnd] = mid.tokenIndices(); this.link( tokens, midStart, omitLast ? midEnd : last.tokenIndices()[1], this.decodeWikitext(s) ); } static headingRe = /^(={1,6})\s*(.+?)\s*(\1)\s*(?=<!--|$)/dg; headingCallback(tokens, pre, mid, post) { if (/{{|<\/?ref(?:\s[^>]*)?>|\[(?:https?:)?\/\/[^\s\[\]]+\]/i.test(mid.s)) return; let s = this.decodeWikitext(mid.s).replace( /'''(.+?)'''|\[\[:?(?:[^|\]]+\|)?([^\]]+)\]\]|<\/?(?:abbr|b|bdi|bdo|big|cite|code|data|del|dfn|em|font|i|ins|kbd|mark|nowiki|q|rb|rp|rt|rtc|ruby|s|samp|small|span|strike|strong|sub|sup|templatestyles|time|translate|tt|u|var)(?:\s[^>]*)?>|<!--.*?-->|\[(?:https?:)?\/\/[^\s\[\]]+\s([^\]]+)\]/gi, '$1$2$3' ).replace(/''(.+?)''/g, '$1').replace(/^[\s_]+|[\s_]+$/g, ''); let t = mw.Title.newFromText( `${!this.isView || !this.isSamePage ? this.getProp() : ''}#${s}` ); if (!t) return; let midIndices = mid.tokenIndices(); if (tokens.slice(...midIndices).some(({ link }) => link)) { this.link(tokens, ...post.tokenIndices(), t); this.link(tokens, ...pre.tokenIndices(), t); } else { this.link(tokens, ...midIndices, t); } } // https://commons.wikimedia.org/wiki/Special:MediaStatistics static galleryRe = /^\s*((?:[^<>\[\]{|}])+\.(?:apng|djv|djvu|flac|gif|jpe|jpeg|jpg|jps|kar|m4a|m4b|m4p|m4r|m4v|mid|midi|mp2|mp3|mp4|mpa|mpe|mpeg|mpg|mpga|oga|ogg|ogm|ogv|ogx|opus|pdf|png|spx|stl|svg|tif|tiff|wav|webm|webp|xcf))\s*(?:\||$)/dgi; galleryCallback(tokens, mid) { let s = this.decodeWikitext(mid.s, true); let t = mw.Title.newFromText(s, 6); if (t && t.getNamespaceId() !== 6) { t = mw.Title.makeTitle(6, s); } if (!t) return; this.link(tokens, ...mid.tokenIndices(), t); } link(tokens, start, end, mwtOrUrl, noRedirect) { let indices = [], last; tokens.slice(start, end).forEach((token, i) => { if (!token.s && !token.link && !token.esc) return; if (token.s && !token.link) { if (!indices.length || last?.link || last?.esc) { indices.push([start + i]); } indices.at(-1)[1] = start + i + 1; } last = token; }); if (indices.some(chunkIndices => chunkIndices.length !== 2)) { mw.notify('Corrupt chunks found'); debugger; } if (!indices.length) return; let attribs = { class: 'smartdiff-link' }, obj; if (typeof mwtOrUrl === 'string') { attribs.class += ' external'; attribs.href = mwtOrUrl; attribs.rel = 'nofollow'; } else { let title = mwtOrUrl.toText(); if (title) { if (Object.hasOwn(this.titles, title)) { obj = this.titles[title]; if (obj.classes) { attribs.class += ' ' + obj.classes.join(' '); } } else { obj = { links: [] }; this.titles[title] = obj; } let fragment; if (obj.url) { attribs.href = obj.url; fragment = mwtOrUrl.getFragment(); } else { let params = obj.red && { action: 'edit', redlink: 1 } || noRedirect && obj.redirect && { redirect: 'no' }; if (obj.canonical) { attribs.href = mw.util.getUrl(obj.canonical, params); fragment = mwtOrUrl.getFragment(); } else { attribs.href = mwtOrUrl.getUrl(params); } } if (fragment) { attribs.href += mw.util.getUrl('#' + fragment); } attribs.title = obj.canonical || title; } else { attribs.class += ' mw-selflink-fragment'; attribs.href = mwtOrUrl.getUrl(); } } let links = indices.reverse().map(chunkIndices => ( this.linkChunk(tokens, ...chunkIndices, attribs) )); if (obj && !obj.processed) { obj.links.push(...links); if (noRedirect) { links.forEach(link => { this.noRedirLinks.add(link); }); } } this.divHasLink = true; } linkChunk(tokens, start, end, attribs) { let newStart = start, newEnd = end; let mid = tokens.slice(start, end); let midTags = mid.filter(({ s }) => !s); for (let i = 0; ; i += 2) { if (tokens[newStart - 1]?.openingTag && midTags[i]?.closingTag && tokens[newStart - 1].openingTag.tagName === midTags[i].closingTag.tagName ) { midTags.unshift(tokens[newStart - 1]); newStart--; } else { break; } } for (let i = midTags.length - 1; ; i--) { if (tokens[newEnd]?.closingTag && midTags[i]?.openingTag && tokens[newEnd].closingTag.tagName === midTags[i].openingTag.tagName ) { midTags.push(tokens[newEnd]); newEnd++; } else { break; } } if (start - newStart) { console.log(`Moved up ${start - newStart} times`); } if (start - newStart > 1) { mw.notify(`Moved up ${start - newStart} times`); } if (newEnd - end) { console.log(`Moved down ${newEnd - end} times`); } if (newEnd - end > 1) { mw.notify(`Moved down ${newEnd - end} times`); } let link = $('<a>').attr(attribs)[0]; let pre = [{ openingTag: link, link }]; let post = [{ closingTag: link, link }]; if (midTags[0]?.closingTag) { pre.unshift({ ...midTags[0] }); pre.push({ openingTag: midTags[0].closingTag }); } if (midTags.at(-1)?.openingTag) { post.unshift({ closingTag: midTags.at(-1).openingTag }); post.push({ ...midTags.at(-1) }); } tokens.splice(newEnd, 0, ...post); tokens.splice(newStart, 0, ...pre); mid.forEach(token => { if (token.s) { token.link = link; } }); return link; } decodeWikitext(text, decodePercents) { let s = text; if (decodePercents) { try { s = decodeURIComponent(s); } catch {} } return $($.parseHTML(s)).text(); } async getSubpage(s, fallbackNs) { if (await this.canHaveSubpages()) { return mw.Title.newFromText( this.getProp() + s.replace(/\/+$/, '') ); } return mw.Title.newFromText(s, fallbackNs); } async getParentPage(s, fallbackNs) { if (await this.canHaveSubpages()) { let chunks = s.split('/'); let levelCount = chunks.findIndex(v => v !== '..'); let sup = this.getProp().split('/').slice(0, -levelCount).join('/'); if (sup) { let sub = chunks.slice(levelCount).join('/').replace(/\/+$/, ''); return mw.Title.newFromText(sub ? `${sup}/${sub}` : sup); } } return mw.Title.newFromText(s, fallbackNs); } async canHaveSubpages(ns = this.getProp('ns')) { SmartDiff.subNs = SmartDiff.subNs || mw.config.get('wgVisualEditorConfig')?.namespacesWithSubpages || Object.values((await new mw.Api().get({ action: 'query', meta: 'siteinfo', siprop: 'namespaces', formatversion: 2 })).query.namespaces).filter(n => n.subpages).map(n => n.id); return SmartDiff.subNs.includes(ns); } getProp(n = 'pn') { if (this[this.side]) { this.sidePropUsed = !this.isSamePage; return this[this.side][n]; } if (Object.hasOwn(this, n)) { return this[n]; } this.pn = mw.config.get('wgPageName'); this.ns = mw.config.get('wgNamespaceNumber'); return this[n]; } async queryTitles() { let unprocessed = Object.entries(this.titles) .filter(([, v]) => !v.processed).slice(0, 500).map(([k]) => k); while (unprocessed.length) { let curTitles = unprocessed.slice(0, 50); curTitles.forEach(title => { this.titles[title].processed = true; }); let { query } = await new mw.Api().post({ action: 'query', titles: curTitles, iwurl: 1, prop: 'info', inprop: 'linkclasses', inlinkcontext: this.getProp(), formatversion: 2 }, { headers: { 'Promise-Non-Write-API-Action': 1 } }); query.pages?.forEach(p => { let obj = (this.titles[p.title] ??= {}); let classes = p.linkclasses || []; if (p.missing && !p.known) { classes.push('new'); obj.red = true; } else if (p.redirect) { obj.redirect = true; } if (classes.length) { obj.classes = classes; } }); query.interwiki?.forEach(iw => { this.titles[iw.title] = { classes: ['extiw'], url: iw.url }; }); query.normalized?.forEach(({ from, to }) => { this.titles[from] = { ...this.titles[from], ...this.titles[to], canonical: to }; }); curTitles.forEach(title => { let obj = this.titles[title]; if (obj.classes) { $(obj.links).addClass(obj.classes); } if (obj.redirect) { let noRedirLinks = this.noRedirLinks; $(obj.links).attr('href', function () { return mw.util.getUrl( obj.canonical || title, noRedirLinks.has(this) && { redirect: 'no' } ) + this.hash; }); } else { let url = obj.url || obj.red && mw.util.getUrl( obj.canonical || title, { action: 'edit', redlink: 1 } ) || obj.canonical && mw.util.getUrl(obj.canonical); if (url) { $(obj.links).attr('href', function () { return url + this.hash; }); } } if (obj.canonical) { $(obj.links).attr('title', obj.canonical); } obj.links = []; }); unprocessed = unprocessed.slice(50); } } static sds = new WeakMap(); static magicWords = [ '!', '=', 'BASEPAGENAME', 'BASEPAGENAME:', 'BASEPAGENAMEE', 'BASEPAGENAMEE:', 'canonicalurl:', 'CURRENTDAY', 'CURRENTDAY2', 'CURRENTDAYNAME', 'CURRENTDOW', 'CURRENTHOUR', 'CURRENTMONTH', 'CURRENTMONTH1', 'CURRENTMONTHABBREV', 'CURRENTMONTHNAME', 'CURRENTMONTHNAMEGEN', 'CURRENTTIME', 'CURRENTTIMESTAMP', 'CURRENTVERSION', 'CURRENTWEEK', 'CURRENTYEAR', 'DEFAULTCATEGORYSORT:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DISPLAYTITLE:', 'filepath:', 'formatnum:', 'FULLPAGENAME', 'FULLPAGENAME:', 'FULLPAGENAMEE', 'FULLPAGENAMEE:', 'fullurl:', 'gender:', 'lc:', 'lcfirst:', 'LOCALDAY', 'LOCALDAY2', 'LOCALDAYNAME', 'LOCALDOW', 'LOCALHOUR', 'LOCALMONTH', 'LOCALMONTH1', 'LOCALMONTHABBREV', 'LOCALMONTHNAME', 'LOCALMONTHNAMEGEN', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCALWEEK', 'LOCALYEAR','NAMESPACE', 'NAMESPACE:', 'NAMESPACEE', 'NAMESPACEE:', 'NAMESPACENUMBER', 'NAMESPACENUMBER:', 'ns:', 'NUMBEROFACTIVEUSERS', 'NUMBEROFARTICLES', 'NUMBEROFEDITS', 'NUMBEROFFILES', 'NUMBEROFPAGES', 'NUMBEROFUSERS', 'padleft:', 'PAGENAME', 'PAGENAMEE', 'PAGESINCAT:', 'PAGESINCATEGORY:', 'plural:', 'REVISIONDAY', 'REVISIONDAY:', 'REVISIONDAY2', 'REVISIONDAY2:', 'REVISIONID', 'REVISIONID:', 'REVISIONMONTH', 'REVISIONMONTH:', 'REVISIONMONTH1', 'REVISIONMONTH1:', 'REVISIONSIZE', 'REVISIONTIMESTAMP', 'REVISIONTIMESTAMP:', 'REVISIONUSER', 'REVISIONUSER:', 'REVISIONYEAR', 'REVISIONYEAR:', 'ROOTPAGENAME', 'ROOTPAGENAME:', 'ROOTPAGENAMEE', 'ROOTPAGENAMEE:', 'SHORTDESC:', 'SUBJECTPAGENAME', 'SUBJECTPAGENAME:', 'SUBJECTPAGENAMEE', 'SUBJECTPAGENAMEE:', 'SUBJECTSPACE', 'SUBJECTSPACE:', 'SUBJECTSPACEE', 'SUBJECTSPACEE:', 'SUBPAGENAME', 'SUBPAGENAME:', 'SUBPAGENAMEE', 'SUBPAGENAMEE:', 'TALKPAGENAME', 'TALKPAGENAME:', 'TALKPAGENAMEE', 'TALKPAGENAMEE:', 'TALKSPACE', 'TALKSPACE:', 'TALKSPACEE', 'TALKSPACEE:', 'uc:', 'ucfirst:', 'urlencode:' ]; } if (Array.isArray(window.smartdiffMagicWords)) { SmartDiff.magicWords.push(...window.smartdiffMagicWords); } if (Array.isArray(window.smartdiffTemplates)) { SmartDiff.templates = window.smartdiffTemplates; } mw.hook('wikipage.diff').add((window.sdcb = ($diff => { window.sd = new SmartDiff($diff); }))); mw.hook('wikipage.diff.wikitextBodyUpdate').add((window.sdcbu = ($rows => { let $diff = $rows.closest('.diff'); let sd = SmartDiff.sds.get($diff[0]); if (sd) { sd.init($rows.filter(function () { return this.checkVisibility(); })); } else { window.sd = new SmartDiff($diff); } }))); }); s2ghymttwyluza113eu4hr9qapj9jph 769766 769765 2026-10-22T16:25:51Z Nardog 40946 769766 javascript text/javascript mw.hook('wikipage.diff').remove(window.sdcb); mw.hook('wikipage.diff.wikitextBodyUpdate').remove(window.sdcbu); $('.smartdiff-link').contents().unwrap().end().remove(); $(':is(.diff-addedline, .diff-addedline, .diff-context) > div, .mw-diff-inline-added, .mw-diff-inline-deleted, .mw-diff-inline-changed').contents().each(function () { if (this.previousSibling && this.previousSibling.tagName === this.tagName) { this.previousSibling.textContent += this.textContent; this.remove(); } }); window.smartdiffTemplates = [ { names: ['T', 'Tl'], namespace: 10, forceNs: true, end: 1 }, { names: ['Tlx'], namespace: 10, end: 1 }, { names: ['U'], prefix: 'Special:Contributions/', end: 1 }, { names: ['Re', 'Reply to', 'Ping'], prefix: 'Special:Contributions/' }, { names: ['About'], start: 3, skipEven: true }, { names: ['For'], start: 2 }, { names: ['Other uses', 'Otheruses'], end: 1 }, { names: ['Section link', 'Slink'], end: 1 }, { names: ['Redirect'], skipEven: true, noRedirectEnd: 1 }, { names: ['Shortcut'], noRedirectStart: 1 }, { names: ['Tracked', 'Phab'], prefix: 'phab:', end: 1 }, { names: [ 'Distinguish', 'Main', 'Main article', 'Further', 'See also', 'Seealso' ] }, { names: ['Ll'], end: 1 } ]; mw.loader.using([ 'mediawiki.util', 'mediawiki.Title', 'mediawiki.api' ], () => { mw.loader.addStyleTag(`body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external) { color: #36b; } body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external):visited { color: #636; } body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external):active { color: #b63; }`); class SmartDiff { constructor($diff) { this.now = performance.now(); this.$diff = $diff; this.isView = mw.config.get('wgNamespaceNumber') !== -1 && mw.config.get('wgAction') === 'view' && $diff.nextAll().is('.diff-hr'); [ ['old', '#mw-diff-otitle1 a, #differences-prevlink'], ['new', '#mw-diff-ntitle1 a, #differences-nextlink'] ].forEach(([side, selector]) => { let link = this.$diff[0].querySelector(selector); let pn = link && mw.util.getParamValue('title', link.search); if (pn) { this[side] = { pn, ns: mw.Title.newFromText(pn).getNamespaceId() }; } }); this.isSamePage = this.old?.pn === this.new?.pn; this.titles = {}; this.noRedirLinks = new WeakSet(); SmartDiff.sds.set($diff[0], this); this.init(); } async init($rows = this.$diff) { this.side = 'old'; for (let div of $rows.find( '.diff-deletedline > div, .mw-diff-inline-deleted' )) { await this.processLine(div); } this.side = 'new'; for (let div of $rows.find( '.diff-addedline > div, .mw-diff-inline-added, .mw-diff-inline-context' )) { await this.processLine(div); } for (let div of $rows.find( '.mw-diff-inline-changed, .mw-diff-inline-moved' )) { await this.processLine(div, true); } let $contexts = $rows.find('.diff-context > div'), clones = []; for (let [i, div] of $contexts.get().entries()) { if (i % 2) { this.side = 'new'; if (this.divHasLink) { if (this.sidePropUsed) { await this.processLine(div); } else { div.replaceChildren( ...$contexts.eq(i - 1).contents().clone() ); clones.push(div); } } } else { this.side = 'old'; await this.processLine(div); } } $(clones).find('.smartdiff-link[title]').each((_, link) => { this.titles[link.title]?.links.push(link); }); this.queryTitles(); if (this.hasError) { mw.notify('SmartDiff error', { type: 'warn' }); } console.log(performance.now() - this.now); } async processLine(div, isInlineChange) { this.divHasLink = false; this.sidePropUsed = false; if (div.querySelector('a[href]')) return; let tokens; if (isInlineChange) { tokens = this.tokenize( div, 'del, .mw-diff-movedpara-left, .mw-diff-movedpara-right' ); this.side = 'new'; await this.exec(tokens); this.escapeTags(tokens, 'ins'); this.unescapeTags(tokens, 'del'); this.side = 'old'; await this.exec(tokens, true); this.unescapeTags(tokens); } else { tokens = this.tokenize(div); await this.exec(tokens); } if (!this.divHasLink) return; try { let newDiv = this.unescape(tokens); this.verify(div, newDiv); div.replaceChildren(...newDiv.childNodes); } catch (e) { debugger; if (typeof e === 'string') { this.hasError = true; console.warn(`SmartDiff error: ${e}`); } else { throw e; } } } tokenize(el, escSelector) { return [...el.childNodes].flatMap(node => { if (node.nodeType === 3) { return node.textContent.split('').map(s => ({ s })); } if (node.nodeType !== 1) { return []; } if (escSelector && node.matches(escSelector)) { return [ { openingTag: node }, { esc: this.tokenize(node, escSelector), tag: node }, { closingTag: node } ]; } return [ { openingTag: node }, ...this.tokenize(node, escSelector), { closingTag: node } ]; }); } escapeTags(tokens, selector) { let openTags = [], data = []; tokens.forEach((token, i) => { if (token.openingTag?.matches(selector)) { openTags.push([token.openingTag, i + 1]); } else if (token.closingTag && openTags.length && token.closingTag.tagName === openTags.at(-1)[0].tagName ) { data.push([...openTags.pop(), i]); } }); data.reverse().forEach(([tag, start, end]) => { let token = { tag }; token.esc = tokens.splice(start, end - start, token); }); } unescapeTags(tokens, selector) { tokens.splice(0, Infinity, ...tokens.flatMap(token => ( token.esc && (!selector || token.tag.matches(selector)) ? token.esc : [token] ))); } unescape(tokens) { let els = [$('<div>')[0]], lastText = ''; tokens.forEach(token => { if (token.openingTag) { if (lastText) { els.at(-1).append(lastText); lastText = ''; } let el = token.openingTag; if (!token.link) { el = el.cloneNode(); } els.at(-1).append(el); els.push(el); } else if (token.closingTag) { let el = els.pop(); if (!els.length) { throw `too many closing tags.\n\n${el.innerHTML}`; } if (el.tagName !== token.closingTag.tagName) { throw `expected </${ token.closingTag.tagName }>, got </${el.tagName}>.\n\n${els[0].innerHTML}`; } if (lastText) { el.append(lastText); lastText = ''; } } else { lastText += token.s; } }); if (lastText) { els.at(-1).append(lastText); } if (els.length !== 1) { throw `too many opening tags.\n\n${els[0].innerHTML}`; } return els[0]; } verify(div, newDiv) { let origHtml = div.innerHTML; let $comp = $(newDiv).clone(); $comp.find('.smartdiff-link').contents().unwrap(); let comp = $comp.html().replace(/<\/(ins|del)><\1(?: [^>]+)?>/g, ''); if (comp !== origHtml) { throw `changed substance.\n\nOriginal:\n${origHtml}\n\nCleaned:\n${comp}\n\nFull:\n${newDiv.innerHTML}`; } let emptyCells = newDiv.querySelectorAll(':is(ins, del):empty'); if (emptyCells.length) { console.log('Empty cells found:', ...emptyCells); mw.notify('Empty cells found'); } } async exec(tokens, isSecond) { let s = tokens.map(token => token.s || '').join(''); let modes = isSecond ? ['url', 'link', 'template', 'gallery'] : ['url', 'link', 'template', 'heading', 'gallery']; for (let mode of modes) { await this.search(s, tokens, mode); } } async search(s, tokens, mode, data) { for (let match of s.matchAll(SmartDiff[mode + 'Re'])) { await this[mode + 'Callback']( tokens, ...match.indices.slice(1).map((indices, i) => indices && { s: match[i + 1], indices, tokens, tokenIndices: SmartDiff.tokenIndices }), data ); } } static tokenIndices() { let count = 0, start; for (let [i, token] of this.tokens.entries()) { if (token.s) { if (count === this.indices[0]) { start = i; } if (count === this.indices[1] - 1) { return [start, i + 1]; } count++; } } } static linkRe = /\[\[\s*(?:<tvar(?: [^>]*)?>\s*)?((?:[^<>\[\]{|}])+?)(?:\s*<\/tvar>|\{\{#translation:\s*\}\})?\s*(?:\||\]\])/dg; async linkCallback(tokens, mid) { let s = this.decodeWikitext(mid.s, true); let t; if (s.startsWith('/')) { t = await this.getSubpage(s); } else if (s.startsWith('#') && (!this.isView || !this.isSamePage)) { t = mw.Title.newFromText(this.getProp() + s); } else if (s.startsWith('../')) { t = await this.getParentPage(s); } else { t = mw.Title.newFromText(s); } if (!t) return; this.link(tokens, ...mid.tokenIndices(), t); } static templateRe = /((?<!{){{\s*(?:(?:#invoke|(?:safe)?subst|msg(?:nw)?|raw|int):\s*)?(?:<tvar(?: [^>]*)?>\s*)?)([^<>\[\]{|}]+?)((?:\s*<\/tvar>)?\s*(\|.*)?(?:}}|$))/dg; async templateCallback(tokens, pre, mid, post, args) { let s = this.decodeWikitext(mid.s, true); let t; if (pre.s.includes('invoke')) { t = mw.Title.makeTitle(828, s); } else if (s.startsWith('#')) { return; } else if (pre.s.includes('int')) { t = mw.Title.makeTitle(8, s); } else if (s.startsWith('/')) { t = await this.getSubpage(s, 10); } else if (s.startsWith('../')) { t = await this.getParentPage(s, 10); } else { if (!pre.s.includes('msg') && !pre.s.includes('raw')) { let match = s.match(/^[^:]+(?::(?=.)|$)/); if (match && SmartDiff.magicWords.includes(match[0])) return; } t = mw.Title.newFromText(s, 10); } if (t) { this.link(tokens, ...mid.tokenIndices(), t); } if (!args) return; let [postStart, postEnd] = post.tokenIndices(); let newPost = tokens.slice(postStart, postEnd); await this.search(post.s, newPost, 'template'); if (!t || !SmartDiff.templates) return; let name = t.getMainText(); for (let data of SmartDiff.templates) { if (Array.isArray(data?.names) && Array.prototype.includes.call(data.names, name) ) { await this.search( post.s, newPost, 'templateArgs', { ...data, i: 1 } ); } } tokens.splice(postStart, postEnd - postStart, ...newPost); } static templateArgsRe = /\|\s*(?:([^=|]*?)\s*=)?\s*(?:<tvar(?: [^>]*)?>\s*)?(.*?)(?:\s*<\/tvar>)?\s*(?=\||{{!}}|}}|$)/dg; templateArgsCallback(tokens, name, mid, data) { let n = name ? Number(name.s) || name.s : data.i++; if (typeof n !== 'number' || ( n < data.start || n > data.end || (n % 2 ? data.skipOdd : data.skipEven) )) { return; } if (!mid.s) return; let s = this.decodeWikitext(mid.s); if (data.prefix) { s = data.prefix + s; } if (data.suffix) { s += data.suffix; } let t = data.forceNs ? mw.Title.makeTitle(data.namespace, s) : mw.Title.newFromText(s, data.namespace); if (!t) return; this.link( tokens, ...mid.tokenIndices(), t, n >= data.noRedirectStart || n <= data.noRedirectEnd ); } static urlRe = /(\[(?=.+\]))?((?:\bhttps?:)?\/\/[^\s"<>\[\]{|}]*)([^\s"<>\[\]{|}])/dg; urlCallback(tokens, pre, mid, last) { let omitLast; if (!pre) { if (mid.s.startsWith('//')) return; if (last.s === ';') { let match = mid.s.match(/&#?[\da-z]+$/i); if (match) { let source = match[0] + last.s; omitLast = this.decodeWikitext(source) === source; } else { omitLast = true; } } else { omitLast = '!,.:?'.includes(last.s) || last.s === ')' && mid.s.includes('('); } } let s = mid.s; if (!omitLast) { s += last.s; } let [midStart, midEnd] = mid.tokenIndices(); this.link( tokens, midStart, omitLast ? midEnd : last.tokenIndices()[1], this.decodeWikitext(s) ); } static headingRe = /^(={1,6})\s*(.+?)\s*(\1)\s*(?=<!--|$)/dg; headingCallback(tokens, pre, mid, post) { if (/{{|<\/?ref(?:\s[^>]*)?>|\[(?:https?:)?\/\/[^\s\[\]]+\]/i.test(mid.s)) return; let s = this.decodeWikitext(mid.s).replace( /'''(.+?)'''|\[\[:?(?:[^|\]]+\|)?([^\]]+)\]\]|<\/?(?:abbr|b|bdi|bdo|big|cite|code|data|del|dfn|em|font|i|ins|kbd|mark|nowiki|q|rb|rp|rt|rtc|ruby|s|samp|small|span|strike|strong|sub|sup|templatestyles|time|translate|tt|u|var)(?:\s[^>]*)?>|<!--.*?-->|\[(?:https?:)?\/\/[^\s\[\]]+\s([^\]]+)\]/gi, '$1$2$3' ).replace(/''(.+?)''/g, '$1').replace(/^[\s_]+|[\s_]+$/g, ''); let t = mw.Title.newFromText( `${!this.isView || !this.isSamePage ? this.getProp() : ''}#${s}` ); if (!t) return; let midIndices = mid.tokenIndices(); if (tokens.slice(...midIndices).some(({ link }) => link)) { this.link(tokens, ...post.tokenIndices(), t); this.link(tokens, ...pre.tokenIndices(), t); } else { this.link(tokens, ...midIndices, t); } } // https://commons.wikimedia.org/wiki/Special:MediaStatistics static galleryRe = /^\s*((?:[^<>\[\]{|}])+\.(?:apng|djv|djvu|flac|gif|jpe|jpeg|jpg|jps|kar|m4a|m4b|m4p|m4r|m4v|mid|midi|mp2|mp3|mp4|mpa|mpe|mpeg|mpg|mpga|oga|ogg|ogm|ogv|ogx|opus|pdf|png|spx|stl|svg|tif|tiff|wav|webm|webp|xcf))\s*(?:\||$)/dgi; galleryCallback(tokens, mid) { let s = this.decodeWikitext(mid.s, true); let t = mw.Title.newFromText(s, 6); if (t && t.getNamespaceId() !== 6) { t = mw.Title.makeTitle(6, s); } if (!t) return; this.link(tokens, ...mid.tokenIndices(), t); } link(tokens, start, end, mwtOrUrl, noRedirect) { let indices = [], last; tokens.slice(start, end).forEach((token, i) => { if (!token.s && !token.link && !token.esc) return; if (token.s && !token.link) { if (!indices.length || last?.link || last?.esc) { indices.push([start + i]); } indices.at(-1)[1] = start + i + 1; } last = token; }); if (indices.some(chunkIndices => chunkIndices.length !== 2)) { mw.notify('Corrupt chunks found'); debugger; } if (!indices.length) return; let attribs = { class: 'smartdiff-link' }, obj; if (typeof mwtOrUrl === 'string') { attribs.class += ' external'; attribs.href = mwtOrUrl; attribs.rel = 'nofollow'; } else { let title = mwtOrUrl.toText(); if (title) { if (Object.hasOwn(this.titles, title)) { obj = this.titles[title]; if (obj.classes) { attribs.class += ' ' + obj.classes.join(' '); } } else { obj = { links: [] }; this.titles[title] = obj; } let fragment; if (obj.url) { attribs.href = obj.url; fragment = mwtOrUrl.getFragment(); } else { let params = obj.red && { action: 'edit', redlink: 1 } || noRedirect && obj.redirect && { redirect: 'no' }; if (obj.canonical) { attribs.href = mw.util.getUrl(obj.canonical, params); fragment = mwtOrUrl.getFragment(); } else { attribs.href = mwtOrUrl.getUrl(params); } } if (fragment) { attribs.href += mw.util.getUrl('#' + fragment); } attribs.title = obj.canonical || title; } else { attribs.class += ' mw-selflink-fragment'; attribs.href = mwtOrUrl.getUrl(); } } let links = indices.reverse().map(chunkIndices => ( this.linkChunk(tokens, ...chunkIndices, attribs) )); if (obj && !obj.processed) { obj.links.push(...links); if (noRedirect) { links.forEach(link => { this.noRedirLinks.add(link); }); } } this.divHasLink = true; } linkChunk(tokens, start, end, attribs) { let newStart = start, newEnd = end; let mid = tokens.slice(start, end); let midTags = mid.filter(({ s }) => !s); for (let i = 0; ; i += 2) { if (tokens[newStart - 1]?.openingTag && midTags[i]?.closingTag && tokens[newStart - 1].openingTag.tagName === midTags[i].closingTag.tagName ) { midTags.unshift(tokens[newStart - 1]); newStart--; } else { break; } } for (let i = midTags.length - 1; ; i--) { if (tokens[newEnd]?.closingTag && midTags[i]?.openingTag && tokens[newEnd].closingTag.tagName === midTags[i].openingTag.tagName ) { midTags.push(tokens[newEnd]); newEnd++; } else { break; } } if (start - newStart) { console.log(`Moved up ${start - newStart} times`); } if (start - newStart > 1) { mw.notify(`Moved up ${start - newStart} times`); } if (newEnd - end) { console.log(`Moved down ${newEnd - end} times`); } if (newEnd - end > 1) { mw.notify(`Moved down ${newEnd - end} times`); } let link = $('<a>').attr(attribs)[0]; let pre = [{ openingTag: link, link }]; let post = [{ closingTag: link, link }]; if (midTags[0]?.closingTag) { pre.unshift({ ...midTags[0] }); pre.push({ openingTag: midTags[0].closingTag }); } if (midTags.at(-1)?.openingTag) { post.unshift({ closingTag: midTags.at(-1).openingTag }); post.push({ ...midTags.at(-1) }); } tokens.splice(newEnd, 0, ...post); tokens.splice(newStart, 0, ...pre); mid.forEach(token => { if (token.s) { token.link = link; } }); return link; } decodeWikitext(text, decodePercents) { let s = text; if (decodePercents) { try { s = decodeURIComponent(s); } catch {} } return $($.parseHTML(s)).text(); } async getSubpage(s, fallbackNs) { if (await this.canHaveSubpages()) { return mw.Title.newFromText( this.getProp() + s.replace(/\/+$/, '') ); } return mw.Title.newFromText(s, fallbackNs); } async getParentPage(s, fallbackNs) { if (await this.canHaveSubpages()) { let chunks = s.split('/'); let levelCount = chunks.findIndex(v => v !== '..'); let sup = this.getProp().split('/').slice(0, -levelCount).join('/'); if (sup) { let sub = chunks.slice(levelCount).join('/').replace(/\/+$/, ''); return mw.Title.newFromText(sub ? `${sup}/${sub}` : sup); } } return mw.Title.newFromText(s, fallbackNs); } async canHaveSubpages(ns = this.getProp('ns')) { SmartDiff.subNs = SmartDiff.subNs || mw.config.get('wgVisualEditorConfig')?.namespacesWithSubpages || Object.values((await new mw.Api().get({ action: 'query', meta: 'siteinfo', siprop: 'namespaces', formatversion: 2 })).query.namespaces).filter(n => n.subpages).map(n => n.id); return SmartDiff.subNs.includes(ns); } getProp(n = 'pn') { if (this[this.side]) { this.sidePropUsed = !this.isSamePage; return this[this.side][n]; } if (Object.hasOwn(this, n)) { return this[n]; } this.pn = mw.config.get('wgPageName'); this.ns = mw.config.get('wgNamespaceNumber'); return this[n]; } async queryTitles() { let unprocessed = Object.entries(this.titles) .filter(([, v]) => !v.processed).slice(0, 500).map(([k]) => k); while (unprocessed.length) { let curTitles = unprocessed.slice(0, 50); curTitles.forEach(title => { this.titles[title].processed = true; }); let { query } = await new mw.Api().post({ action: 'query', titles: curTitles, iwurl: 1, prop: 'info', inprop: 'linkclasses', inlinkcontext: this.getProp(), formatversion: 2 }, { headers: { 'Promise-Non-Write-API-Action': 1 } }); query.pages?.forEach(p => { let obj = (this.titles[p.title] ??= {}); let classes = p.linkclasses || []; if (p.missing && !p.known) { classes.push('new'); obj.red = true; } else if (p.redirect) { obj.redirect = true; } if (classes.length) { obj.classes = classes; } }); query.interwiki?.forEach(iw => { this.titles[iw.title] = { classes: ['extiw'], url: iw.url }; }); query.normalized?.forEach(({ from, to }) => { this.titles[from] = { ...this.titles[from], ...this.titles[to], canonical: to }; }); curTitles.forEach(title => { let obj = this.titles[title]; if (obj.classes) { $(obj.links).addClass(obj.classes); } if (obj.redirect) { let noRedirLinks = this.noRedirLinks; $(obj.links).attr('href', function () { return mw.util.getUrl( obj.canonical || title, noRedirLinks.has(this) && { redirect: 'no' } ) + this.hash; }); } else { let url = obj.url || obj.red && mw.util.getUrl( obj.canonical || title, { action: 'edit', redlink: 1 } ) || obj.canonical && mw.util.getUrl(obj.canonical); if (url) { $(obj.links).attr('href', function () { return url + this.hash; }); } } if (obj.canonical) { $(obj.links).attr('title', obj.canonical); } obj.links = []; }); unprocessed = unprocessed.slice(50); } } static sds = new WeakMap(); static magicWords = [ '!', '=', 'BASEPAGENAME', 'BASEPAGENAME:', 'BASEPAGENAMEE', 'BASEPAGENAMEE:', 'canonicalurl:', 'CURRENTDAY', 'CURRENTDAY2', 'CURRENTDAYNAME', 'CURRENTDOW', 'CURRENTHOUR', 'CURRENTMONTH', 'CURRENTMONTH1', 'CURRENTMONTHABBREV', 'CURRENTMONTHNAME', 'CURRENTMONTHNAMEGEN', 'CURRENTTIME', 'CURRENTTIMESTAMP', 'CURRENTVERSION', 'CURRENTWEEK', 'CURRENTYEAR', 'DEFAULTCATEGORYSORT:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DISPLAYTITLE:', 'filepath:', 'formatnum:', 'FULLPAGENAME', 'FULLPAGENAME:', 'FULLPAGENAMEE', 'FULLPAGENAMEE:', 'fullurl:', 'gender:', 'lc:', 'lcfirst:', 'LOCALDAY', 'LOCALDAY2', 'LOCALDAYNAME', 'LOCALDOW', 'LOCALHOUR', 'LOCALMONTH', 'LOCALMONTH1', 'LOCALMONTHABBREV', 'LOCALMONTHNAME', 'LOCALMONTHNAMEGEN', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCALWEEK', 'LOCALYEAR','NAMESPACE', 'NAMESPACE:', 'NAMESPACEE', 'NAMESPACEE:', 'NAMESPACENUMBER', 'NAMESPACENUMBER:', 'ns:', 'NUMBEROFACTIVEUSERS', 'NUMBEROFARTICLES', 'NUMBEROFEDITS', 'NUMBEROFFILES', 'NUMBEROFPAGES', 'NUMBEROFUSERS', 'padleft:', 'PAGENAME', 'PAGENAMEE', 'PAGESINCAT:', 'PAGESINCATEGORY:', 'plural:', 'REVISIONDAY', 'REVISIONDAY:', 'REVISIONDAY2', 'REVISIONDAY2:', 'REVISIONID', 'REVISIONID:', 'REVISIONMONTH', 'REVISIONMONTH:', 'REVISIONMONTH1', 'REVISIONMONTH1:', 'REVISIONSIZE', 'REVISIONTIMESTAMP', 'REVISIONTIMESTAMP:', 'REVISIONUSER', 'REVISIONUSER:', 'REVISIONYEAR', 'REVISIONYEAR:', 'ROOTPAGENAME', 'ROOTPAGENAME:', 'ROOTPAGENAMEE', 'ROOTPAGENAMEE:', 'SHORTDESC:', 'SUBJECTPAGENAME', 'SUBJECTPAGENAME:', 'SUBJECTPAGENAMEE', 'SUBJECTPAGENAMEE:', 'SUBJECTSPACE', 'SUBJECTSPACE:', 'SUBJECTSPACEE', 'SUBJECTSPACEE:', 'SUBPAGENAME', 'SUBPAGENAME:', 'SUBPAGENAMEE', 'SUBPAGENAMEE:', 'TALKPAGENAME', 'TALKPAGENAME:', 'TALKPAGENAMEE', 'TALKPAGENAMEE:', 'TALKSPACE', 'TALKSPACE:', 'TALKSPACEE', 'TALKSPACEE:', 'uc:', 'ucfirst:', 'urlencode:' ]; } if (Array.isArray(window.smartdiffMagicWords)) { SmartDiff.magicWords.push(...window.smartdiffMagicWords); } if (Array.isArray(window.smartdiffTemplates)) { SmartDiff.templates = window.smartdiffTemplates; } mw.hook('wikipage.diff').add((window.sdcb = ($diff => { window.sd = new SmartDiff($diff); }))); mw.hook('wikipage.diff.wikitextBodyUpdate').add((window.sdcbu = ($rows => { let $diff = $rows.closest('.diff'); let sd = SmartDiff.sds.get($diff[0]); if (sd) { sd.init($rows.filter(function () { return this.checkVisibility(); })); } else { window.sd = new SmartDiff($diff); } }))); }); bz6pjqkrr48e97xwe3drrcwtph3xqel 769767 769766 2026-10-22T16:46:47Z Nardog 40946 769767 javascript text/javascript mw.hook('wikipage.diff').remove(window.sdcb); mw.hook('wikipage.diff.wikitextBodyUpdate').remove(window.sdcbu); $('.smartdiff-link').contents().unwrap().end().remove(); $(':is(.diff-addedline, .diff-addedline, .diff-context) > div, .mw-diff-inline-added, .mw-diff-inline-deleted, .mw-diff-inline-changed').contents().each(function () { if (this.previousSibling && this.previousSibling.tagName === this.tagName) { this.previousSibling.textContent += this.textContent; this.remove(); } }); window.smartdiffTemplates = [ { names: ['T', 'Tl'], namespace: 10, forceNs: true, end: 1 }, { names: ['Tlx'], namespace: 10, end: 1 }, { names: ['U'], prefix: 'Special:Contributions/', end: 1 }, { names: ['Re', 'Reply to', 'Ping'], prefix: 'Special:Contributions/' }, { names: ['About'], start: 3, skipEven: true }, { names: ['For'], start: 2 }, { names: ['Other uses', 'Otheruses'], end: 1 }, { names: ['Section link', 'Slink'], end: 1 }, { names: ['Redirect'], skipEven: true, noRedirectEnd: 1 }, { names: ['Shortcut'], noRedirectStart: 1 }, { names: ['Tracked', 'Phab'], prefix: 'phab:', end: 1 }, { names: [ 'Distinguish', 'Main', 'Main article', 'Further', 'See also', 'Seealso' ] }, { names: ['Ll'], end: 1 } ]; mw.loader.using([ 'mediawiki.util', 'mediawiki.Title', 'mediawiki.api' ], () => { mw.loader.addStyleTag(`body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external) { color: #36b; } body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external):visited { color: #636; } body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external):active { color: #b63; }`); class SmartDiff { constructor($diff) { this.now = performance.now(); this.$diff = $diff; this.isView = mw.config.get('wgNamespaceNumber') !== -1 && mw.config.get('wgAction') === 'view' && $diff.nextAll().is('.diff-hr'); [ ['old', '#mw-diff-otitle1 a, #differences-prevlink'], ['new', '#mw-diff-ntitle1 a, #differences-nextlink'] ].forEach(([side, selector]) => { let link = this.$diff[0].querySelector(selector); let pn = link && mw.util.getParamValue('title', link.search); if (pn) { this[side] = { pn, ns: mw.Title.newFromText(pn).getNamespaceId() }; } }); this.isSamePage = this.old?.pn === this.new?.pn; this.titles = {}; this.noRedirLinks = new WeakSet(); SmartDiff.sds.set($diff[0], this); this.init(); } async init($rows = this.$diff) { this.side = 'old'; for (let div of $rows.find( '.diff-deletedline > div, .mw-diff-inline-deleted' )) { await this.processLine(div); } this.side = 'new'; for (let div of $rows.find( '.diff-addedline > div, .mw-diff-inline-added, .mw-diff-inline-context' )) { await this.processLine(div); } for (let div of $rows.find( '.mw-diff-inline-changed, .mw-diff-inline-moved' )) { await this.processLine(div, true); } let $contexts = $rows.find('.diff-context > div'), clones = []; for (let [i, div] of $contexts.get().entries()) { if (i % 2) { this.side = 'new'; if (this.divHasLink) { if (this.sidePropUsed) { await this.processLine(div); } else { div.replaceChildren( ...$contexts.eq(i - 1).contents().clone() ); clones.push(div); } } } else { this.side = 'old'; await this.processLine(div); } } $(clones).find('.smartdiff-link[title]').each((_, link) => { this.titles[link.title]?.links.push(link); }); this.queryTitles(); if (this.hasError) { mw.notify('SmartDiff error', { type: 'warn' }); } console.log(performance.now() - this.now); } async processLine(div, isInlineChange) { this.divHasLink = false; this.sidePropUsed = false; if (div.querySelector('a[href]')) return; let tokens; if (isInlineChange) { tokens = this.tokenize( div, 'del, .mw-diff-movedpara-left, .mw-diff-movedpara-right' ); this.side = 'new'; await this.exec(tokens); this.escapeTags(tokens, 'ins'); this.unescapeTags(tokens, 'del'); this.side = 'old'; await this.exec(tokens, true); this.unescapeTags(tokens); } else { tokens = this.tokenize(div); await this.exec(tokens); } if (!this.divHasLink) return; try { let newDiv = this.unescape(tokens); this.verify(div, newDiv); div.replaceChildren(...newDiv.childNodes); } catch (e) { debugger; if (typeof e === 'string') { this.hasError = true; console.warn(`SmartDiff error: ${e}`); } else { throw e; } } } tokenize(el, escSelector) { return [...el.childNodes].flatMap(node => { if (node.nodeType === 3) { return node.textContent.split('').map(s => ({ s })); } if (node.nodeType !== 1) { return []; } if (escSelector && node.matches(escSelector)) { return [ { openingTag: node }, { esc: this.tokenize(node, escSelector), tag: node }, { closingTag: node } ]; } return [ { openingTag: node }, ...this.tokenize(node, escSelector), { closingTag: node } ]; }); } escapeTags(tokens, selector) { let openTags = [], data = []; tokens.forEach((token, i) => { if (token.openingTag?.matches(selector)) { openTags.push([token.openingTag, i + 1]); } else if (token.closingTag && openTags.length && token.closingTag.tagName === openTags.at(-1)[0].tagName ) { data.push([...openTags.pop(), i]); } }); data.reverse().forEach(([tag, start, end]) => { let token = { tag }; token.esc = tokens.splice(start, end - start, token); }); } unescapeTags(tokens, selector) { tokens.splice(0, Infinity, ...tokens.flatMap(token => ( token.esc && (!selector || token.tag.matches(selector)) ? token.esc : [token] ))); } unescape(tokens) { let els = [$('<div>')[0]], lastText = ''; tokens.forEach(token => { if (token.openingTag) { if (lastText) { els.at(-1).append(lastText); lastText = ''; } let el = token.openingTag; if (!token.link) { el = el.cloneNode(); } els.at(-1).append(el); els.push(el); } else if (token.closingTag) { let el = els.pop(); if (!els.length) { throw `too many closing tags.\n\n${el.innerHTML}`; } if (el.tagName !== token.closingTag.tagName) { throw `expected </${ token.closingTag.tagName }>, got </${el.tagName}>.\n\n${els[0].innerHTML}`; } if (lastText) { el.append(lastText); lastText = ''; } } else { lastText += token.s; } }); if (lastText) { els.at(-1).append(lastText); } if (els.length !== 1) { throw `too many opening tags.\n\n${els[0].innerHTML}`; } return els[0]; } verify(div, newDiv) { let origHtml = div.innerHTML; let $comp = $(newDiv).clone(); $comp.find('.smartdiff-link').contents().unwrap(); let comp = $comp.html().replace(/<\/(ins|del)><\1(?: [^>]+)?>/g, ''); if (comp !== origHtml) { throw `changed substance.\n\nOriginal:\n${origHtml}\n\nCleaned:\n${comp}\n\nFull:\n${newDiv.innerHTML}`; } let emptyCells = newDiv.querySelectorAll(':is(ins, del):empty'); if (emptyCells.length) { console.log('Empty cells found:', ...emptyCells); mw.notify('Empty cells found'); } } async exec(tokens, isSecond) { let s = tokens.map(token => token.s || '').join(''); let modes = isSecond ? ['url', 'link', 'template', 'gallery'] : ['url', 'link', 'template', 'heading', 'gallery']; for (let mode of modes) { await this.search(s, tokens, mode); } } async search(s, tokens, mode, data) { for (let match of s.matchAll(SmartDiff[mode + 'Re'])) { await this[mode + 'Callback']( tokens, ...match.indices.slice(1).map((indices, i) => indices && { s: match[i + 1], indices, tokens, tokenIndices: SmartDiff.tokenIndices }), data ); } } static tokenIndices() { let count = 0, start; for (let [i, token] of this.tokens.entries()) { if (token.s) { if (count === this.indices[0]) { start = i; } if (count === this.indices[1] - 1) { return [start, i + 1]; } count++; } } } static linkRe = /\[\[\s*(?:<tvar(?: [^>]*)?>\s*)?((?:[^<>\[\]{|}])+?)(?:\s*<\/tvar>|\{\{#translation:\s*\}\})?\s*(?:\||\]\])/dg; async linkCallback(tokens, mid) { let s = this.decodeWikitext(mid.s, true); let t; if (s.startsWith('/')) { t = await this.getSubpage(s); } else if (s.startsWith('#') && (!this.isView || !this.isSamePage)) { t = mw.Title.newFromText(this.getProp() + s); } else if (s.startsWith('../')) { t = await this.getParentPage(s); } else { t = mw.Title.newFromText(s); } if (!t) return; this.link(tokens, ...mid.tokenIndices(), t); } static templateRe = /((?<!{){{\s*(?:(?:#invoke|(?:safe)?subst|msg(?:nw)?|raw|int):\s*)?(?:<tvar(?: [^>]*)?>\s*)?)([^<>\[\]{|}]+?)((?:\s*<\/tvar>)?\s*(\|.*)?(?:}}|$))/dg; async templateCallback(tokens, pre, mid, post, args) { let s = this.decodeWikitext(mid.s, true); let t; if (pre.s.includes('invoke')) { t = mw.Title.makeTitle(828, s); } else if (s.startsWith('#')) { return; } else if (pre.s.includes('int')) { t = mw.Title.makeTitle(8, s); } else if (s.startsWith('/')) { t = await this.getSubpage(s, 10); } else if (s.startsWith('../')) { t = await this.getParentPage(s, 10); } else { if (!pre.s.includes('msg') && !pre.s.includes('raw')) { let match = s.match(/^[^:]+(?::(?=.)|$)/); if (match && SmartDiff.magicWords.includes(match[0])) return; } t = mw.Title.newFromText(s, 10); } if (t) { this.link(tokens, ...mid.tokenIndices(), t); } if (!args) return; let [postStart, postEnd] = post.tokenIndices(); let newPost = tokens.slice(postStart, postEnd); await this.search(post.s, newPost, 'template'); if (!t || !SmartDiff.templates) return; let name = t.getMainText(); for (let data of SmartDiff.templates) { if (Array.isArray(data?.names) && Array.prototype.includes.call(data.names, name) ) { await this.search( post.s, newPost, 'templateArgs', { ...data, i: 1 } ); } } tokens.splice(postStart, postEnd - postStart, ...newPost); } static templateArgsRe = /\|\s*(?:([^=|]*?)\s*=)?\s*(?:<tvar(?: [^>]*)?>\s*)?(.*?)(?:\s*<\/tvar>)?\s*(?=\||{{!}}|}}|$)/dg; templateArgsCallback(tokens, name, mid, data) { let n = name ? Number(name.s) || name.s : data.i++; if (typeof n !== 'number' || ( n < data.start || n > data.end || (n % 2 ? data.skipOdd : data.skipEven) )) { return; } if (!mid.s) return; let s = this.decodeWikitext(mid.s); if (data.prefix) { s = data.prefix + s; } if (data.suffix) { s += data.suffix; } let t = data.forceNs ? mw.Title.makeTitle(data.namespace, s) : mw.Title.newFromText(s, data.namespace); if (!t) return; this.link( tokens, ...mid.tokenIndices(), t, n >= data.noRedirectStart || n <= data.noRedirectEnd ); } static urlRe = /(\[(?=.+\]))?((?:\bhttps?:)?\/\/[^\s"<>\[\]{|}]*)([^\s"<>\[\]{|}])/dg; urlCallback(tokens, pre, mid, last) { let omitLast; if (!pre) { if (mid.s.startsWith('//')) return; if (last.s === ';') { let match = mid.s.match(/&#?[\da-z]+$/i); if (match) { let source = match[0] + last.s; omitLast = this.decodeWikitext(source) === source; } else { omitLast = true; } } else { omitLast = '!,.:?'.includes(last.s) || last.s === ')' && mid.s.includes('('); } } let s = mid.s; if (!omitLast) { s += last.s; } let [midStart, midEnd] = mid.tokenIndices(); this.link( tokens, midStart, omitLast ? midEnd : last.tokenIndices()[1], this.decodeWikitext(s) ); } static headingRe = /^(={1,6})\s*(.+?)\s*(\1)\s*(?=<!--|$)/dg; headingCallback(tokens, pre, mid, post) { if (/{{|<\/?ref(?:\s[^>]*)?>|\[(?:https?:)?\/\/[^\s\[\]]+\]/i.test(mid.s)) return; let s = this.decodeWikitext(mid.s).replace( /'''(.+?)'''|\[\[:?(?:[^|\]]+\|)?([^\]]+)\]\]|<\/?(?:abbr|b|bdi|bdo|big|cite|code|data|del|dfn|em|font|i|ins|kbd|mark|nowiki|q|rb|rp|rt|rtc|ruby|s|samp|small|span|strike|strong|sub|sup|templatestyles|time|translate|tt|u|var)(?:\s[^>]*)?>|<!--.*?-->|\[(?:https?:)?\/\/[^\s\[\]]+\s([^\]]+)\]/gi, '$1$2$3' ).replace(/''(.+?)''/g, '$1').replace(/^[\s_]+|[\s_]+$/g, ''); let t = mw.Title.newFromText( `${!this.isView || !this.isSamePage ? this.getProp() : ''}#${s}` ); if (!t) return; let midIndices = mid.tokenIndices(); if (tokens.slice(...midIndices).some(({ link }) => link)) { this.link(tokens, ...post.tokenIndices(), t); this.link(tokens, ...pre.tokenIndices(), t); } else { this.link(tokens, ...midIndices, t); } } // https://commons.wikimedia.org/wiki/Special:MediaStatistics static galleryRe = /^\s*((?:[^<>\[\]{|}])+\.(?:apng|djv|djvu|flac|gif|jpe|jpeg|jpg|jps|kar|m4a|m4b|m4p|m4r|m4v|mid|midi|mp2|mp3|mp4|mpa|mpe|mpeg|mpg|mpga|oga|ogg|ogm|ogv|ogx|opus|pdf|png|spx|stl|svg|tif|tiff|wav|webm|webp|xcf))\s*(?:\||$)/dgi; galleryCallback(tokens, mid) { let s = this.decodeWikitext(mid.s, true); let t = mw.Title.newFromText(s, 6); if (t && t.getNamespaceId() !== 6) { t = mw.Title.makeTitle(6, s); } if (!t) return; this.link(tokens, ...mid.tokenIndices(), t); } link(tokens, start, end, mwtOrUrl, noRedirect) { let indices = [], last; tokens.slice(start, end).forEach((token, i) => { if (!token.s && !token.link && !token.esc) return; if (token.s && !token.link) { if (!indices.length || last?.link || last?.esc) { indices.push([start + i]); } indices.at(-1)[1] = start + i + 1; } last = token; }); if (indices.some(chunkIndices => chunkIndices.length !== 2)) { mw.notify('Corrupt chunks found'); debugger; } if (!indices.length) return; let attribs = { class: 'smartdiff-link' }, obj; if (typeof mwtOrUrl === 'string') { attribs.class += ' external'; attribs.href = mwtOrUrl; attribs.rel = 'nofollow'; } else { let title = mwtOrUrl.toText(); if (title) { if (Object.hasOwn(this.titles, title)) { obj = this.titles[title]; if (obj.classes) { attribs.class += ' ' + obj.classes.join(' '); } } else { obj = { links: [] }; this.titles[title] = obj; } let fragment; if (obj.url) { attribs.href = obj.url; fragment = mwtOrUrl.getFragment(); } else { let params = obj.red && { action: 'edit', redlink: 1 } || noRedirect && obj.redirect && { redirect: 'no' }; if (obj.canonical) { attribs.href = mw.util.getUrl(obj.canonical, params); fragment = mwtOrUrl.getFragment(); } else { attribs.href = mwtOrUrl.getUrl(params); } } if (fragment) { attribs.href += mw.util.getUrl('#' + fragment); } attribs.title = obj.canonical || title; } else { attribs.class += ' mw-selflink-fragment'; attribs.href = mwtOrUrl.getUrl(); } } let links = indices.reverse().map(chunkIndices => ( this.linkChunk(tokens, ...chunkIndices, attribs) )); if (obj && !obj.processed) { obj.links.push(...links); if (noRedirect) { links.forEach(link => { this.noRedirLinks.add(link); }); } } this.divHasLink = true; } linkChunk(tokens, start, end, attribs) { let newStart = start, newEnd = end; let mid = tokens.slice(start, end); let midTags = mid.filter(token => token.openingTag || token.closingTag); for (let i = 0; ; i += 2) { if (tokens[newStart - 1]?.openingTag && midTags[i]?.closingTag && tokens[newStart - 1].openingTag.tagName === midTags[i].closingTag.tagName ) { midTags.unshift(tokens[newStart - 1]); newStart--; } else { break; } } for (let i = midTags.length - 1; ; i--) { if (tokens[newEnd]?.closingTag && midTags[i]?.openingTag && tokens[newEnd].closingTag.tagName === midTags[i].openingTag.tagName ) { midTags.push(tokens[newEnd]); newEnd++; } else { break; } } if (start - newStart) { console.log(`Moved up ${start - newStart} times`); } if (start - newStart > 1) { mw.notify(`Moved up ${start - newStart} times`); } if (newEnd - end) { console.log(`Moved down ${newEnd - end} times`); } if (newEnd - end > 1) { mw.notify(`Moved down ${newEnd - end} times`); } let link = $('<a>').attr(attribs)[0]; let pre = [{ openingTag: link, link }]; let post = [{ closingTag: link, link }]; if (midTags[0]?.closingTag) { pre.unshift({ ...midTags[0] }); pre.push({ openingTag: midTags[0].closingTag }); } if (midTags.at(-1)?.openingTag) { post.unshift({ closingTag: midTags.at(-1).openingTag }); post.push({ ...midTags.at(-1) }); } tokens.splice(newEnd, 0, ...post); tokens.splice(newStart, 0, ...pre); mid.forEach(token => { if (token.s) { token.link = link; } }); return link; } decodeWikitext(text, decodePercents) { let s = text; if (decodePercents) { try { s = decodeURIComponent(s); } catch {} } return $($.parseHTML(s)).text(); } async getSubpage(s, fallbackNs) { if (await this.canHaveSubpages()) { return mw.Title.newFromText( this.getProp() + s.replace(/\/+$/, '') ); } return mw.Title.newFromText(s, fallbackNs); } async getParentPage(s, fallbackNs) { if (await this.canHaveSubpages()) { let chunks = s.split('/'); let levelCount = chunks.findIndex(v => v !== '..'); let sup = this.getProp().split('/').slice(0, -levelCount).join('/'); if (sup) { let sub = chunks.slice(levelCount).join('/').replace(/\/+$/, ''); return mw.Title.newFromText(sub ? `${sup}/${sub}` : sup); } } return mw.Title.newFromText(s, fallbackNs); } async canHaveSubpages(ns = this.getProp('ns')) { SmartDiff.subNs = SmartDiff.subNs || mw.config.get('wgVisualEditorConfig')?.namespacesWithSubpages || Object.values((await new mw.Api().get({ action: 'query', meta: 'siteinfo', siprop: 'namespaces', formatversion: 2 })).query.namespaces).filter(n => n.subpages).map(n => n.id); return SmartDiff.subNs.includes(ns); } getProp(n = 'pn') { if (this[this.side]) { this.sidePropUsed = !this.isSamePage; return this[this.side][n]; } if (Object.hasOwn(this, n)) { return this[n]; } this.pn = mw.config.get('wgPageName'); this.ns = mw.config.get('wgNamespaceNumber'); return this[n]; } async queryTitles() { let unprocessed = Object.entries(this.titles) .filter(([, v]) => !v.processed).slice(0, 500).map(([k]) => k); while (unprocessed.length) { let curTitles = unprocessed.slice(0, 50); curTitles.forEach(title => { this.titles[title].processed = true; }); let { query } = await new mw.Api().post({ action: 'query', titles: curTitles, iwurl: 1, prop: 'info', inprop: 'linkclasses', inlinkcontext: this.getProp(), formatversion: 2 }, { headers: { 'Promise-Non-Write-API-Action': 1 } }); query.pages?.forEach(p => { let obj = (this.titles[p.title] ??= {}); let classes = p.linkclasses || []; if (p.missing && !p.known) { classes.push('new'); obj.red = true; } else if (p.redirect) { obj.redirect = true; } if (classes.length) { obj.classes = classes; } }); query.interwiki?.forEach(iw => { this.titles[iw.title] = { classes: ['extiw'], url: iw.url }; }); query.normalized?.forEach(({ from, to }) => { this.titles[from] = { ...this.titles[from], ...this.titles[to], canonical: to }; }); curTitles.forEach(title => { let obj = this.titles[title]; if (obj.classes) { $(obj.links).addClass(obj.classes); } if (obj.redirect) { let noRedirLinks = this.noRedirLinks; $(obj.links).attr('href', function () { return mw.util.getUrl( obj.canonical || title, noRedirLinks.has(this) && { redirect: 'no' } ) + this.hash; }); } else { let url = obj.url || obj.red && mw.util.getUrl( obj.canonical || title, { action: 'edit', redlink: 1 } ) || obj.canonical && mw.util.getUrl(obj.canonical); if (url) { $(obj.links).attr('href', function () { return url + this.hash; }); } } if (obj.canonical) { $(obj.links).attr('title', obj.canonical); } obj.links = []; }); unprocessed = unprocessed.slice(50); } } static sds = new WeakMap(); static magicWords = [ '!', '=', 'BASEPAGENAME', 'BASEPAGENAME:', 'BASEPAGENAMEE', 'BASEPAGENAMEE:', 'canonicalurl:', 'CURRENTDAY', 'CURRENTDAY2', 'CURRENTDAYNAME', 'CURRENTDOW', 'CURRENTHOUR', 'CURRENTMONTH', 'CURRENTMONTH1', 'CURRENTMONTHABBREV', 'CURRENTMONTHNAME', 'CURRENTMONTHNAMEGEN', 'CURRENTTIME', 'CURRENTTIMESTAMP', 'CURRENTVERSION', 'CURRENTWEEK', 'CURRENTYEAR', 'DEFAULTCATEGORYSORT:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DISPLAYTITLE:', 'filepath:', 'formatnum:', 'FULLPAGENAME', 'FULLPAGENAME:', 'FULLPAGENAMEE', 'FULLPAGENAMEE:', 'fullurl:', 'gender:', 'lc:', 'lcfirst:', 'LOCALDAY', 'LOCALDAY2', 'LOCALDAYNAME', 'LOCALDOW', 'LOCALHOUR', 'LOCALMONTH', 'LOCALMONTH1', 'LOCALMONTHABBREV', 'LOCALMONTHNAME', 'LOCALMONTHNAMEGEN', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCALWEEK', 'LOCALYEAR','NAMESPACE', 'NAMESPACE:', 'NAMESPACEE', 'NAMESPACEE:', 'NAMESPACENUMBER', 'NAMESPACENUMBER:', 'ns:', 'NUMBEROFACTIVEUSERS', 'NUMBEROFARTICLES', 'NUMBEROFEDITS', 'NUMBEROFFILES', 'NUMBEROFPAGES', 'NUMBEROFUSERS', 'padleft:', 'PAGENAME', 'PAGENAMEE', 'PAGESINCAT:', 'PAGESINCATEGORY:', 'plural:', 'REVISIONDAY', 'REVISIONDAY:', 'REVISIONDAY2', 'REVISIONDAY2:', 'REVISIONID', 'REVISIONID:', 'REVISIONMONTH', 'REVISIONMONTH:', 'REVISIONMONTH1', 'REVISIONMONTH1:', 'REVISIONSIZE', 'REVISIONTIMESTAMP', 'REVISIONTIMESTAMP:', 'REVISIONUSER', 'REVISIONUSER:', 'REVISIONYEAR', 'REVISIONYEAR:', 'ROOTPAGENAME', 'ROOTPAGENAME:', 'ROOTPAGENAMEE', 'ROOTPAGENAMEE:', 'SHORTDESC:', 'SUBJECTPAGENAME', 'SUBJECTPAGENAME:', 'SUBJECTPAGENAMEE', 'SUBJECTPAGENAMEE:', 'SUBJECTSPACE', 'SUBJECTSPACE:', 'SUBJECTSPACEE', 'SUBJECTSPACEE:', 'SUBPAGENAME', 'SUBPAGENAME:', 'SUBPAGENAMEE', 'SUBPAGENAMEE:', 'TALKPAGENAME', 'TALKPAGENAME:', 'TALKPAGENAMEE', 'TALKPAGENAMEE:', 'TALKSPACE', 'TALKSPACE:', 'TALKSPACEE', 'TALKSPACEE:', 'uc:', 'ucfirst:', 'urlencode:' ]; } if (Array.isArray(window.smartdiffMagicWords)) { SmartDiff.magicWords.push(...window.smartdiffMagicWords); } if (Array.isArray(window.smartdiffTemplates)) { SmartDiff.templates = window.smartdiffTemplates; } mw.hook('wikipage.diff').add((window.sdcb = ($diff => { window.sd = new SmartDiff($diff); }))); mw.hook('wikipage.diff.wikitextBodyUpdate').add((window.sdcbu = ($rows => { let $diff = $rows.closest('.diff'); let sd = SmartDiff.sds.get($diff[0]); if (sd) { sd.init($rows.filter(function () { return this.checkVisibility(); })); } else { window.sd = new SmartDiff($diff); } }))); }); h5kw42nx4g7od0c5izyrxfqkfw7ezmp 769768 769767 2026-10-22T18:33:53Z Nardog 40946 769768 javascript text/javascript mw.hook('wikipage.diff').remove(window.sdcb); mw.hook('wikipage.diff.wikitextBodyUpdate').remove(window.sdcbu); $('.smartdiff-link').contents().unwrap().end().remove(); $(':is(.diff-addedline, .diff-addedline, .diff-context) > div, .mw-diff-inline-added, .mw-diff-inline-deleted, .mw-diff-inline-changed').contents().each(function () { if (this.previousSibling && this.previousSibling.tagName === this.tagName) { this.previousSibling.textContent += this.textContent; this.remove(); } }); window.smartdiffTemplates = [ { names: ['T', 'Tl'], namespace: 10, forceNs: true, end: 1 }, { names: ['Tlx'], namespace: 10, end: 1 }, { names: ['U'], prefix: 'Special:Contributions/', end: 1 }, { names: ['Re', 'Reply to', 'Ping'], prefix: 'Special:Contributions/' }, { names: ['About'], start: 3, skipEven: true }, { names: ['For'], start: 2 }, { names: ['Other uses', 'Otheruses'], end: 1 }, { names: ['Section link', 'Slink'], end: 1 }, { names: ['Redirect'], skipEven: true, noRedirectEnd: 1 }, { names: ['Shortcut'], noRedirectStart: 1 }, { names: ['Tracked', 'Phab'], prefix: 'phab:', end: 1 }, { names: [ 'Distinguish', 'Main', 'Main article', 'Further', 'See also', 'Seealso' ] }, { names: ['Ll'], end: 1 } ]; mw.loader.using([ 'mediawiki.util', 'mediawiki.Title', 'mediawiki.api' ], () => { mw.loader.addStyleTag(`body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external) { color: #36b; } body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external):visited { color: #636; } body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external):active { color: #b63; }`); class SmartDiff { constructor($diff) { this.now = performance.now(); this.$diff = $diff; this.isView = mw.config.get('wgNamespaceNumber') !== -1 && mw.config.get('wgAction') === 'view' && $diff.nextAll().is('.diff-hr'); [ ['old', '#mw-diff-otitle1 a, #differences-prevlink'], ['new', '#mw-diff-ntitle1 a, #differences-nextlink'] ].forEach(([side, selector]) => { let link = this.$diff[0].querySelector(selector); let pn = link && mw.util.getParamValue('title', link.search); if (pn) { this[side] = { pn, ns: mw.Title.newFromText(pn).getNamespaceId() }; } }); this.isSamePage = this.old?.pn === this.new?.pn; this.titles = {}; this.noRedirLinks = new WeakSet(); SmartDiff.sds.set($diff[0], this); this.init(); } async init($rows = this.$diff) { this.side = 'old'; for (let div of $rows.find( '.diff-deletedline > div, .mw-diff-inline-deleted' )) { await this.processLine(div); } this.side = 'new'; for (let div of $rows.find( '.diff-addedline > div, .mw-diff-inline-added, .mw-diff-inline-context' )) { await this.processLine(div); } for (let div of $rows.find( '.mw-diff-inline-changed, .mw-diff-inline-moved' )) { await this.processLine(div, true); } let $contexts = $rows.find('.diff-context > div'), clones = []; for (let [i, div] of $contexts.get().entries()) { if (i % 2) { this.side = 'new'; if (this.divHasLink) { if (this.sidePropUsed) { await this.processLine(div); } else { div.replaceChildren( ...$contexts.eq(i - 1).contents().clone() ); clones.push(div); } } } else { this.side = 'old'; await this.processLine(div); } } $(clones).find('.smartdiff-link[title]').each((_, link) => { this.titles[link.title]?.links.push(link); }); this.queryTitles(); if (this.hasError) { mw.notify('SmartDiff error', { type: 'warn' }); } console.log(performance.now() - this.now); } async processLine(div, isInlineChange) { this.divHasLink = false; this.sidePropUsed = false; if (div.querySelector('a[href]')) return; let tokens; if (isInlineChange) { tokens = this.tokenize( div, 'del, .mw-diff-movedpara-left, .mw-diff-movedpara-right' ); this.side = 'new'; await this.exec(tokens); this.escapeTags(tokens, 'ins'); this.unescapeTags(tokens, 'del'); this.side = 'old'; await this.exec(tokens, true); this.unescapeTags(tokens); } else { tokens = this.tokenize(div); await this.exec(tokens); } if (!this.divHasLink) return; try { let newDiv = this.unescape(tokens); this.verify(div, newDiv); div.replaceChildren(...newDiv.childNodes); } catch (e) { debugger; if (typeof e === 'string') { this.hasError = true; console.warn(`SmartDiff error: ${e}`); } else { throw e; } } } tokenize(el, escSelector) { return [...el.childNodes].flatMap(node => { if (node.nodeType === 3) { return node.textContent.split('').map(s => ({ s })); } if (node.nodeType !== 1) { return []; } if (escSelector && node.matches(escSelector)) { return [ { openingTag: node }, { esc: this.tokenize(node), tag: node }, { closingTag: node } ]; } return [ { openingTag: node }, ...this.tokenize(node, escSelector), { closingTag: node } ]; }); } escapeTags(tokens, selector) { let openTags = [], data = []; tokens.forEach((token, i) => { if (token.openingTag?.matches(selector)) { openTags.push([token.openingTag, i + 1]); } else if (token.closingTag && openTags.length && token.closingTag.tagName === openTags.at(-1)[0].tagName ) { data.push([...openTags.pop(), i]); } }); data.reverse().forEach(([tag, start, end]) => { let token = { tag }; token.esc = tokens.splice(start, end - start, token); }); } unescapeTags(tokens, selector) { tokens.splice(0, Infinity, ...tokens.flatMap(token => ( token.esc && (!selector || token.tag.matches(selector)) ? token.esc : [token] ))); } unescape(tokens) { let els = [$('<div>')[0]], lastText = ''; tokens.forEach(token => { if (token.openingTag) { if (lastText) { els.at(-1).append(lastText); lastText = ''; } let el = token.openingTag; if (!token.link) { el = el.cloneNode(); } els.at(-1).append(el); els.push(el); } else if (token.closingTag) { let el = els.pop(); if (!els.length) { throw `too many closing tags.\n\n${el.innerHTML}`; } if (el.tagName !== token.closingTag.tagName) { throw `expected </${ token.closingTag.tagName.toLowerCase() }>, got </${ el.tagName.toLowerCase() }>.\n\n${els[0].innerHTML}`; } if (lastText) { el.append(lastText); lastText = ''; } } else { lastText += token.s; } }); if (lastText) { els.at(-1).append(lastText); } if (els.length !== 1) { throw `too many opening tags.\n\n${els[0].innerHTML}`; } return els[0]; } verify(div, newDiv) { let origHtml = div.innerHTML; let $comp = $(newDiv).clone(); $comp.find('.smartdiff-link').contents().unwrap(); let comp = $comp.html().replace(/<\/(ins|del)><\1(?: [^>]+)?>/g, ''); if (comp !== origHtml) { throw `changed substance.\n\nOriginal:\n${origHtml}\n\nCleaned:\n${comp}\n\nFull:\n${newDiv.innerHTML}`; } let emptyCells = newDiv.querySelectorAll(':is(ins, del):empty'); if (emptyCells.length) { console.log('Empty cells found:', ...emptyCells); mw.notify('Empty cells found'); } } async exec(tokens, isSecond) { let s = tokens.map(token => token.s || '').join(''); let modes = isSecond ? ['url', 'link', 'template', 'gallery'] : ['url', 'link', 'template', 'heading', 'gallery']; for (let mode of modes) { await this.search(s, tokens, mode); } } async search(s, tokens, mode, data) { for (let match of s.matchAll(SmartDiff[mode + 'Re'])) { await this[mode + 'Callback']( tokens, ...match.indices.slice(1).map((indices, i) => indices && { s: match[i + 1], indices, tokens, tokenIndices: SmartDiff.tokenIndices }), data ); } } static tokenIndices() { let count = 0, start; for (let [i, token] of this.tokens.entries()) { if (token.s) { if (count === this.indices[0]) { start = i; } if (count === this.indices[1] - 1) { return [start, i + 1]; } count++; } } } static linkRe = /\[\[\s*(?:<tvar(?: [^>]*)?>\s*)?((?:[^<>\[\]{|}])+?)(?:\s*<\/tvar>|\{\{#translation:\s*\}\})?\s*(?:\||\]\])/dg; async linkCallback(tokens, mid) { let s = this.decodeWikitext(mid.s, true); let t; if (s.startsWith('/')) { t = await this.getSubpage(s); } else if (s.startsWith('#') && (!this.isView || !this.isSamePage)) { t = mw.Title.newFromText(this.getProp() + s); } else if (s.startsWith('../')) { t = await this.getParentPage(s); } else { t = mw.Title.newFromText(s); } if (!t) return; this.link(tokens, ...mid.tokenIndices(), t); } static templateRe = /((?<!{){{\s*(?:(?:#invoke|(?:safe)?subst|msg(?:nw)?|raw|int):\s*)?(?:<tvar(?: [^>]*)?>\s*)?)([^<>\[\]{|}]+?)((?:\s*<\/tvar>)?\s*(\|.*)?(?:}}|$))/dg; async templateCallback(tokens, pre, mid, post, args) { let s = this.decodeWikitext(mid.s, true); let t; if (pre.s.includes('invoke')) { t = mw.Title.makeTitle(828, s); } else if (s.startsWith('#')) { return; } else if (pre.s.includes('int')) { t = mw.Title.makeTitle(8, s); } else if (s.startsWith('/')) { t = await this.getSubpage(s, 10); } else if (s.startsWith('../')) { t = await this.getParentPage(s, 10); } else { if (!pre.s.includes('msg') && !pre.s.includes('raw')) { let match = s.match(/^[^:]+(?::(?=.)|$)/); if (match && SmartDiff.magicWords.includes(match[0])) return; } t = mw.Title.newFromText(s, 10); } if (t) { this.link(tokens, ...mid.tokenIndices(), t); } if (!args) return; let [postStart, postEnd] = post.tokenIndices(); let newPost = tokens.slice(postStart, postEnd); await this.search(post.s, newPost, 'template'); if (!t || !SmartDiff.templates) return; let name = t.getMainText(); for (let data of SmartDiff.templates) { if (Array.isArray(data?.names) && Array.prototype.includes.call(data.names, name) ) { await this.search( post.s, newPost, 'templateArgs', { ...data, i: 1 } ); } } tokens.splice(postStart, postEnd - postStart, ...newPost); } static templateArgsRe = /\|\s*(?:([^=|]*?)\s*=)?\s*(?:<tvar(?: [^>]*)?>\s*)?(.*?)(?:\s*<\/tvar>)?\s*(?=\||{{!}}|}}|$)/dg; templateArgsCallback(tokens, name, mid, data) { let n = name ? Number(name.s) || name.s : data.i++; if (typeof n !== 'number' || ( n < data.start || n > data.end || (n % 2 ? data.skipOdd : data.skipEven) )) { return; } if (!mid.s) return; let s = this.decodeWikitext(mid.s); if (data.prefix) { s = data.prefix + s; } if (data.suffix) { s += data.suffix; } let t = data.forceNs ? mw.Title.makeTitle(data.namespace, s) : mw.Title.newFromText(s, data.namespace); if (!t) return; this.link( tokens, ...mid.tokenIndices(), t, n >= data.noRedirectStart || n <= data.noRedirectEnd ); } static urlRe = /(\[(?=.+\]))?((?:\bhttps?:)?\/\/[^\s"<>\[\]{|}]*)([^\s"<>\[\]{|}])/dg; urlCallback(tokens, pre, mid, last) { let omitLast; if (!pre) { if (mid.s.startsWith('//')) return; if (last.s === ';') { let match = mid.s.match(/&#?[\da-z]+$/i); if (match) { let source = match[0] + last.s; omitLast = this.decodeWikitext(source) === source; } else { omitLast = true; } } else { omitLast = '!,.:?'.includes(last.s) || last.s === ')' && mid.s.includes('('); } } let s = mid.s; if (!omitLast) { s += last.s; } let [midStart, midEnd] = mid.tokenIndices(); this.link( tokens, midStart, omitLast ? midEnd : last.tokenIndices()[1], this.decodeWikitext(s) ); } static headingRe = /^(={1,6})\s*(.+?)\s*(\1)\s*(?=<!--|$)/dg; headingCallback(tokens, pre, mid, post) { if (/{{|<\/?ref(?:\s[^>]*)?>|\[(?:https?:)?\/\/[^\s\[\]]+\]/i.test(mid.s)) return; let s = this.decodeWikitext(mid.s).replace( /'''(.+?)'''|\[\[:?(?:[^|\]]+\|)?([^\]]+)\]\]|<\/?(?:abbr|b|bdi|bdo|big|cite|code|data|del|dfn|em|font|i|ins|kbd|mark|nowiki|q|rb|rp|rt|rtc|ruby|s|samp|small|span|strike|strong|sub|sup|templatestyles|time|translate|tt|u|var)(?:\s[^>]*)?>|<!--.*?-->|\[(?:https?:)?\/\/[^\s\[\]]+\s([^\]]+)\]/gi, '$1$2$3' ).replace(/''(.+?)''/g, '$1').replace(/^[\s_]+|[\s_]+$/g, ''); let t = mw.Title.newFromText( `${!this.isView || !this.isSamePage ? this.getProp() : ''}#${s}` ); if (!t) return; let midIndices = mid.tokenIndices(); if (tokens.slice(...midIndices).some(({ link }) => link)) { this.link(tokens, ...post.tokenIndices(), t); this.link(tokens, ...pre.tokenIndices(), t); } else { this.link(tokens, ...midIndices, t); } } // https://commons.wikimedia.org/wiki/Special:MediaStatistics static galleryRe = /^\s*((?:[^<>\[\]{|}])+\.(?:apng|djv|djvu|flac|gif|jpe|jpeg|jpg|jps|kar|m4a|m4b|m4p|m4r|m4v|mid|midi|mp2|mp3|mp4|mpa|mpe|mpeg|mpg|mpga|oga|ogg|ogm|ogv|ogx|opus|pdf|png|spx|stl|svg|tif|tiff|wav|webm|webp|xcf))\s*(?:\||$)/dgi; galleryCallback(tokens, mid) { let s = this.decodeWikitext(mid.s, true); let t = mw.Title.newFromText(s, 6); if (t && t.getNamespaceId() !== 6) { t = mw.Title.makeTitle(6, s); } if (!t) return; this.link(tokens, ...mid.tokenIndices(), t); } link(tokens, start, end, mwtOrUrl, noRedirect) { let indices = [], last; tokens.slice(start, end).forEach((token, i) => { if (!token.s && !token.link && !token.esc) return; if (token.s && !token.link) { if (!indices.length || last?.link || last?.esc) { indices.push([start + i]); } indices.at(-1)[1] = start + i + 1; } last = token; }); if (indices.some(chunkIndices => chunkIndices.length !== 2)) { mw.notify('Corrupt chunks found'); debugger; } if (!indices.length) return; let attribs = { class: 'smartdiff-link' }, obj; if (typeof mwtOrUrl === 'string') { attribs.class += ' external'; attribs.href = mwtOrUrl; attribs.rel = 'nofollow'; } else { let title = mwtOrUrl.toText(); if (title) { if (Object.hasOwn(this.titles, title)) { obj = this.titles[title]; if (obj.classes) { attribs.class += ' ' + obj.classes.join(' '); } } else { obj = { links: [] }; this.titles[title] = obj; } let fragment; if (obj.url) { attribs.href = obj.url; fragment = mwtOrUrl.getFragment(); } else { let params = obj.red && { action: 'edit', redlink: 1 } || noRedirect && obj.redirect && { redirect: 'no' }; if (obj.canonical) { attribs.href = mw.util.getUrl(obj.canonical, params); fragment = mwtOrUrl.getFragment(); } else { attribs.href = mwtOrUrl.getUrl(params); } } if (fragment) { attribs.href += mw.util.getUrl('#' + fragment); } attribs.title = obj.canonical || title; } else { attribs.class += ' mw-selflink-fragment'; attribs.href = mwtOrUrl.getUrl(); } } let links = indices.reverse().map(chunkIndices => ( this.linkChunk(tokens, ...chunkIndices, attribs) )); if (obj && !obj.processed) { obj.links.push(...links); if (noRedirect) { links.forEach(link => { this.noRedirLinks.add(link); }); } } this.divHasLink = true; } linkChunk(tokens, start, end, attribs) { let newStart = start, newEnd = end; let mid = tokens.slice(start, end); let midTags = mid.filter(token => token.openingTag || token.closingTag); for (let i = 0; ; i += 2) { if (tokens[newStart - 1]?.openingTag && midTags[i]?.closingTag && tokens[newStart - 1].openingTag.tagName === midTags[i].closingTag.tagName ) { midTags.unshift(tokens[newStart - 1]); newStart--; } else { break; } } for (let i = midTags.length - 1; ; i--) { if (tokens[newEnd]?.closingTag && midTags[i]?.openingTag && tokens[newEnd].closingTag.tagName === midTags[i].openingTag.tagName ) { midTags.push(tokens[newEnd]); newEnd++; } else { break; } } if (start - newStart) { console.log(`Moved up ${start - newStart} times`); } if (start - newStart > 1) { mw.notify(`Moved up ${start - newStart} times`); } if (newEnd - end) { console.log(`Moved down ${newEnd - end} times`); } if (newEnd - end > 1) { mw.notify(`Moved down ${newEnd - end} times`); } let link = $('<a>').attr(attribs)[0]; let pre = [{ openingTag: link, link }]; let post = [{ closingTag: link, link }]; if (midTags[0]?.closingTag) { pre.unshift({ ...midTags[0] }); pre.push({ openingTag: midTags[0].closingTag }); } if (midTags.at(-1)?.openingTag) { post.unshift({ closingTag: midTags.at(-1).openingTag }); post.push({ ...midTags.at(-1) }); } tokens.splice(newEnd, 0, ...post); tokens.splice(newStart, 0, ...pre); mid.forEach(token => { if (token.s) { token.link = link; } }); return link; } decodeWikitext(text, decodePercents) { let s = text; if (decodePercents) { try { s = decodeURIComponent(s); } catch {} } return $($.parseHTML(s)).text(); } async getSubpage(s, fallbackNs) { if (await this.canHaveSubpages()) { return mw.Title.newFromText( this.getProp() + s.replace(/\/+$/, '') ); } return mw.Title.newFromText(s, fallbackNs); } async getParentPage(s, fallbackNs) { if (await this.canHaveSubpages()) { let chunks = s.split('/'); let levelCount = chunks.findIndex(v => v !== '..'); let sup = this.getProp().split('/').slice(0, -levelCount).join('/'); if (sup) { let sub = chunks.slice(levelCount).join('/').replace(/\/+$/, ''); return mw.Title.newFromText(sub ? `${sup}/${sub}` : sup); } } return mw.Title.newFromText(s, fallbackNs); } async canHaveSubpages(ns = this.getProp('ns')) { SmartDiff.subNs = SmartDiff.subNs || mw.config.get('wgVisualEditorConfig')?.namespacesWithSubpages || Object.values((await new mw.Api().get({ action: 'query', meta: 'siteinfo', siprop: 'namespaces', formatversion: 2 })).query.namespaces).filter(n => n.subpages).map(n => n.id); return SmartDiff.subNs.includes(ns); } getProp(n = 'pn') { if (this[this.side]) { this.sidePropUsed = !this.isSamePage; return this[this.side][n]; } if (Object.hasOwn(this, n)) { return this[n]; } this.pn = mw.config.get('wgPageName'); this.ns = mw.config.get('wgNamespaceNumber'); return this[n]; } async queryTitles() { let unprocessed = Object.entries(this.titles) .filter(([, v]) => !v.processed).slice(0, 500).map(([k]) => k); while (unprocessed.length) { let curTitles = unprocessed.slice(0, 50); curTitles.forEach(title => { this.titles[title].processed = true; }); let { query } = await new mw.Api().post({ action: 'query', titles: curTitles, iwurl: 1, prop: 'info', inprop: 'linkclasses', inlinkcontext: this.getProp(), formatversion: 2 }, { headers: { 'Promise-Non-Write-API-Action': 1 } }); query.pages?.forEach(p => { let obj = (this.titles[p.title] ??= {}); let classes = p.linkclasses || []; if (p.missing && !p.known) { classes.push('new'); obj.red = true; } else if (p.redirect) { obj.redirect = true; } if (classes.length) { obj.classes = classes; } }); query.interwiki?.forEach(iw => { this.titles[iw.title] = { classes: ['extiw'], url: iw.url }; }); query.normalized?.forEach(({ from, to }) => { this.titles[from] = { ...this.titles[from], ...this.titles[to], canonical: to }; }); curTitles.forEach(title => { let obj = this.titles[title]; if (obj.classes) { $(obj.links).addClass(obj.classes); } if (obj.redirect) { let noRedirLinks = this.noRedirLinks; $(obj.links).attr('href', function () { return mw.util.getUrl( obj.canonical || title, noRedirLinks.has(this) && { redirect: 'no' } ) + this.hash; }); } else { let url = obj.url || obj.red && mw.util.getUrl( obj.canonical || title, { action: 'edit', redlink: 1 } ) || obj.canonical && mw.util.getUrl(obj.canonical); if (url) { $(obj.links).attr('href', function () { return url + this.hash; }); } } if (obj.canonical) { $(obj.links).attr('title', obj.canonical); } obj.links = []; }); unprocessed = unprocessed.slice(50); } } static sds = new WeakMap(); static magicWords = [ '!', '=', 'BASEPAGENAME', 'BASEPAGENAME:', 'BASEPAGENAMEE', 'BASEPAGENAMEE:', 'canonicalurl:', 'CURRENTDAY', 'CURRENTDAY2', 'CURRENTDAYNAME', 'CURRENTDOW', 'CURRENTHOUR', 'CURRENTMONTH', 'CURRENTMONTH1', 'CURRENTMONTHABBREV', 'CURRENTMONTHNAME', 'CURRENTMONTHNAMEGEN', 'CURRENTTIME', 'CURRENTTIMESTAMP', 'CURRENTVERSION', 'CURRENTWEEK', 'CURRENTYEAR', 'DEFAULTCATEGORYSORT:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DISPLAYTITLE:', 'filepath:', 'formatnum:', 'FULLPAGENAME', 'FULLPAGENAME:', 'FULLPAGENAMEE', 'FULLPAGENAMEE:', 'fullurl:', 'gender:', 'lc:', 'lcfirst:', 'LOCALDAY', 'LOCALDAY2', 'LOCALDAYNAME', 'LOCALDOW', 'LOCALHOUR', 'LOCALMONTH', 'LOCALMONTH1', 'LOCALMONTHABBREV', 'LOCALMONTHNAME', 'LOCALMONTHNAMEGEN', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCALWEEK', 'LOCALYEAR','NAMESPACE', 'NAMESPACE:', 'NAMESPACEE', 'NAMESPACEE:', 'NAMESPACENUMBER', 'NAMESPACENUMBER:', 'ns:', 'NUMBEROFACTIVEUSERS', 'NUMBEROFARTICLES', 'NUMBEROFEDITS', 'NUMBEROFFILES', 'NUMBEROFPAGES', 'NUMBEROFUSERS', 'padleft:', 'PAGENAME', 'PAGENAMEE', 'PAGESINCAT:', 'PAGESINCATEGORY:', 'plural:', 'REVISIONDAY', 'REVISIONDAY:', 'REVISIONDAY2', 'REVISIONDAY2:', 'REVISIONID', 'REVISIONID:', 'REVISIONMONTH', 'REVISIONMONTH:', 'REVISIONMONTH1', 'REVISIONMONTH1:', 'REVISIONSIZE', 'REVISIONTIMESTAMP', 'REVISIONTIMESTAMP:', 'REVISIONUSER', 'REVISIONUSER:', 'REVISIONYEAR', 'REVISIONYEAR:', 'ROOTPAGENAME', 'ROOTPAGENAME:', 'ROOTPAGENAMEE', 'ROOTPAGENAMEE:', 'SHORTDESC:', 'SUBJECTPAGENAME', 'SUBJECTPAGENAME:', 'SUBJECTPAGENAMEE', 'SUBJECTPAGENAMEE:', 'SUBJECTSPACE', 'SUBJECTSPACE:', 'SUBJECTSPACEE', 'SUBJECTSPACEE:', 'SUBPAGENAME', 'SUBPAGENAME:', 'SUBPAGENAMEE', 'SUBPAGENAMEE:', 'TALKPAGENAME', 'TALKPAGENAME:', 'TALKPAGENAMEE', 'TALKPAGENAMEE:', 'TALKSPACE', 'TALKSPACE:', 'TALKSPACEE', 'TALKSPACEE:', 'uc:', 'ucfirst:', 'urlencode:' ]; } if (Array.isArray(window.smartdiffMagicWords)) { SmartDiff.magicWords.push(...window.smartdiffMagicWords); } if (Array.isArray(window.smartdiffTemplates)) { SmartDiff.templates = window.smartdiffTemplates; } mw.hook('wikipage.diff').add((window.sdcb = ($diff => { window.sd = new SmartDiff($diff); }))); mw.hook('wikipage.diff.wikitextBodyUpdate').add((window.sdcbu = ($rows => { let $diff = $rows.closest('.diff'); let sd = SmartDiff.sds.get($diff[0]); if (sd) { sd.init($rows.filter(function () { return this.checkVisibility(); })); } else { window.sd = new SmartDiff($diff); } }))); }); nzdzib23bvf41so4wudj4nfa3e5n7cv 769769 769768 2026-10-22T18:34:21Z Nardog 40946 769769 javascript text/javascript mw.hook('wikipage.diff').remove(window.sdcb); mw.hook('wikipage.diff.wikitextBodyUpdate').remove(window.sdcbu); $('.smartdiff-link').contents().unwrap().end().remove(); $(':is(.diff-addedline, .diff-addedline, .diff-context) > div, .mw-diff-inline-added, .mw-diff-inline-deleted, .mw-diff-inline-changed').contents().each(function () { if (this.previousSibling && this.previousSibling.tagName === this.tagName) { this.previousSibling.textContent += this.textContent; this.remove(); } }); window.smartdiffTemplates = [ { names: ['T', 'Tl'], namespace: 10, forceNs: true, end: 1 }, { names: ['Tlx'], namespace: 10, end: 1 }, { names: ['U'], prefix: 'Special:Contributions/', end: 1 }, { names: ['Re', 'Reply to', 'Ping'], prefix: 'Special:Contributions/' }, { names: ['About'], start: 3, skipEven: true }, { names: ['For'], start: 2 }, { names: ['Other uses', 'Otheruses'], end: 1 }, { names: ['Section link', 'Slink'], end: 1 }, { names: ['Redirect'], skipEven: true, noRedirectEnd: 1 }, { names: ['Shortcut'], noRedirectStart: 1 }, { names: ['Tracked', 'Phab'], prefix: 'phab:', end: 1 }, { names: [ 'Distinguish', 'Main', 'Main article', 'Further', 'See also', 'Seealso' ] }, { names: ['Ll'], end: 1 } ]; mw.loader.using([ 'mediawiki.util', 'mediawiki.Title', 'mediawiki.api' ], () => { mw.loader.addStyleTag(`body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external) { color: #36b; } body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external):visited { color: #636; } body:is(.skin-vector-legacy, .skin-monobook) .smartdiff-link:is(.extiw, .external):active { color: #b63; }`); class SmartDiff { constructor($diff) { this.now = performance.now(); this.$diff = $diff; this.isView = mw.config.get('wgNamespaceNumber') !== -1 && mw.config.get('wgAction') === 'view' && $diff.nextAll().is('.diff-hr'); [ ['old', '#mw-diff-otitle1 a, #differences-prevlink'], ['new', '#mw-diff-ntitle1 a, #differences-nextlink'] ].forEach(([side, selector]) => { let link = this.$diff[0].querySelector(selector); let pn = link && mw.util.getParamValue('title', link.search); if (pn) { this[side] = { pn, ns: mw.Title.newFromText(pn).getNamespaceId() }; } }); this.isSamePage = this.old?.pn === this.new?.pn; this.titles = {}; this.noRedirLinks = new WeakSet(); SmartDiff.sds.set($diff[0], this); this.init(); } async init($rows = this.$diff) { this.side = 'old'; for (let div of $rows.find( '.diff-deletedline > div, .mw-diff-inline-deleted' )) { await this.processLine(div); } this.side = 'new'; for (let div of $rows.find( '.diff-addedline > div, .mw-diff-inline-added, .mw-diff-inline-context' )) { await this.processLine(div); } for (let div of $rows.find( '.mw-diff-inline-changed, .mw-diff-inline-moved' )) { await this.processLine(div, true); } let $contexts = $rows.find('.diff-context > div'), clones = []; for (let [i, div] of $contexts.get().entries()) { if (i % 2) { this.side = 'new'; if (this.divHasLink) { if (this.sidePropUsed) { await this.processLine(div); } else { div.replaceChildren( ...$contexts.eq(i - 1).contents().clone() ); clones.push(div); } } } else { this.side = 'old'; await this.processLine(div); } } $(clones).find('.smartdiff-link[title]').each((_, link) => { this.titles[link.title]?.links.push(link); }); this.queryTitles(); if (this.hasError) { mw.notify('SmartDiff error', { type: 'warn' }); } console.log(performance.now() - this.now); } async processLine(div, isInlineChange) { this.divHasLink = false; this.sidePropUsed = false; if (div.querySelector('a[href]')) return; let tokens; if (isInlineChange) { tokens = this.tokenize( div, 'del, .mw-diff-movedpara-left, .mw-diff-movedpara-right' ); this.side = 'new'; await this.exec(tokens); this.escapeTags(tokens, 'ins'); this.unescapeTags(tokens, 'del'); this.side = 'old'; await this.exec(tokens, true); this.unescapeTags(tokens); } else { tokens = this.tokenize(div); await this.exec(tokens); } if (!this.divHasLink) return; try { let newDiv = this.unescape(tokens); this.verify(div, newDiv); div.replaceChildren(...newDiv.childNodes); } catch (e) { debugger; if (typeof e === 'string') { this.hasError = true; console.warn(`SmartDiff error: ${e}`); } else { throw e; } } } tokenize(el, escSelector) { return [...el.childNodes].flatMap(node => { if (node.nodeType === 3) { return node.textContent.split('').map(s => ({ s })); } if (node.nodeType !== 1) { return []; } if (escSelector && node.matches(escSelector)) { return [ { openingTag: node }, { esc: this.tokenize(node), tag: node }, { closingTag: node } ]; } return [ { openingTag: node }, ...this.tokenize(node, escSelector), { closingTag: node } ]; }); } escapeTags(tokens, selector) { let openTags = [], data = []; tokens.forEach((token, i) => { if (token.openingTag?.matches(selector)) { openTags.push([token.openingTag, i + 1]); } else if (token.closingTag && openTags.length && token.closingTag.tagName === openTags.at(-1)[0].tagName ) { data.push([...openTags.pop(), i]); } }); data.reverse().forEach(([tag, start, end]) => { let token = { tag }; token.esc = tokens.splice(start, end - start, token); }); } unescapeTags(tokens, selector) { tokens.splice(0, Infinity, ...tokens.flatMap(token => ( token.esc && (!selector || token.tag.matches(selector)) ? token.esc : [token] ))); } unescape(tokens) { let els = [$('<div>')[0]], lastText = ''; tokens.forEach(token => { if (token.openingTag) { if (lastText) { els.at(-1).append(lastText); lastText = ''; } let el = token.openingTag; if (!token.link) { el = el.cloneNode(); } els.at(-1).append(el); els.push(el); } else if (token.closingTag) { let el = els.pop(); if (!els.length) { throw `too many closing tags.\n\n${el.innerHTML}`; } if (el.tagName !== token.closingTag.tagName) { throw `expected </${ token.closingTag.tagName.toLowerCase() }>, got </${ el.tagName.toLowerCase() }>.\n\n${els[0].innerHTML}`; } if (lastText) { el.append(lastText); lastText = ''; } } else { lastText += token.s; } }); if (lastText) { els.at(-1).append(lastText); } if (els.length !== 1) { throw `too many opening tags.\n\n${els[0].innerHTML}`; } return els[0]; } verify(div, newDiv) { let origHtml = div.innerHTML; let $comp = $(newDiv).clone(); $comp.find('.smartdiff-link').contents().unwrap(); let comp = $comp.html().replace(/<\/(ins|del)><\1(?: [^>]+)?>/g, ''); if (comp !== origHtml) { throw `changed substance.\n\nOriginal:\n${origHtml}\n\nCleaned:\n${comp}\n\nFull:\n${newDiv.innerHTML}`; } let emptyCells = newDiv.querySelectorAll(':is(ins, del):empty'); if (emptyCells.length) { console.log('Empty cells found:', ...emptyCells); mw.notify('Empty cells found'); } } async exec(tokens, isSecond) { let s = tokens.map(token => token.s || '').join(''); let modes = isSecond ? ['url', 'link', 'template', 'gallery'] : ['url', 'link', 'template', 'heading', 'gallery']; for (let mode of modes) { await this.search(s, tokens, mode); } } async search(s, tokens, mode, data) { for (let match of s.matchAll(SmartDiff[mode + 'Re'])) { await this[mode + 'Callback']( tokens, ...match.indices.slice(1).map((indices, i) => indices && { s: match[i + 1], indices, tokens, tokenIndices: SmartDiff.tokenIndices }), data ); } } static tokenIndices() { let count = 0, start; for (let [i, token] of this.tokens.entries()) { if (token.s) { if (count === this.indices[0]) { start = i; } if (count === this.indices[1] - 1) { return [start, i + 1]; } count++; } } } static linkRe = /\[\[\s*(?:<tvar(?: [^>]*)?>\s*)?((?:[^<>\[\]{|}])+?)(?:\s*<\/tvar>|\{\{#translation:\s*\}\})?\s*(?:\||\]\])/dg; async linkCallback(tokens, mid) { let s = this.decodeWikitext(mid.s, true); let t; if (s.startsWith('/')) { t = await this.getSubpage(s); } else if (s.startsWith('#') && (!this.isView || !this.isSamePage)) { t = mw.Title.newFromText(this.getProp() + s); } else if (s.startsWith('../')) { t = await this.getParentPage(s); } else { t = mw.Title.newFromText(s); } if (!t) return; this.link(tokens, ...mid.tokenIndices(), t); } static templateRe = /((?<!{){{\s*(?:(?:#invoke|(?:safe)?subst|msg(?:nw)?|raw|int):\s*)?(?:<tvar(?: [^>]*)?>\s*)?)([^<>\[\]{|}]+?)((?:\s*<\/tvar>)?\s*(\|.*)?(?:}}|$))/dg; async templateCallback(tokens, pre, mid, post, args) { let s = this.decodeWikitext(mid.s, true); let t; if (pre.s.includes('invoke')) { t = mw.Title.makeTitle(828, s); } else if (s.startsWith('#')) { return; } else if (pre.s.includes('int')) { t = mw.Title.makeTitle(8, s); } else if (s.startsWith('/')) { t = await this.getSubpage(s, 10); } else if (s.startsWith('../')) { t = await this.getParentPage(s, 10); } else { if (!pre.s.includes('msg') && !pre.s.includes('raw')) { let match = s.match(/^[^:]+(?::(?=.)|$)/); if (match && SmartDiff.magicWords.includes(match[0])) return; } t = mw.Title.newFromText(s, 10); } if (t) { this.link(tokens, ...mid.tokenIndices(), t); } if (!args) return; let [postStart, postEnd] = post.tokenIndices(); let newPost = tokens.slice(postStart, postEnd); await this.search(post.s, newPost, 'template'); if (!t || !SmartDiff.templates) return; let name = t.getMainText(); for (let data of SmartDiff.templates) { if (Array.isArray(data?.names) && Array.prototype.includes.call(data.names, name) ) { await this.search( post.s, newPost, 'templateArgs', { ...data, i: 1 } ); } } tokens.splice(postStart, postEnd - postStart, ...newPost); } static templateArgsRe = /\|\s*(?:([^=|]*?)\s*=)?\s*(?:<tvar(?: [^>]*)?>\s*)?(.*?)(?:\s*<\/tvar>)?\s*(?=\||{{!}}|}}|$)/dg; templateArgsCallback(tokens, name, mid, data) { let n = name ? Number(name.s) || name.s : data.i++; if (typeof n !== 'number' || ( n < data.start || n > data.end || (n % 2 ? data.skipOdd : data.skipEven) )) { return; } if (!mid.s) return; let s = this.decodeWikitext(mid.s); if (data.prefix) { s = data.prefix + s; } if (data.suffix) { s += data.suffix; } let t = data.forceNs ? mw.Title.makeTitle(data.namespace, s) : mw.Title.newFromText(s, data.namespace); if (!t) return; this.link( tokens, ...mid.tokenIndices(), t, n >= data.noRedirectStart || n <= data.noRedirectEnd ); } static urlRe = /(\[(?=.+\]))?((?:\bhttps?:)?\/\/[^\s"<>\[\]{|}]*)([^\s"<>\[\]{|}])/dg; urlCallback(tokens, pre, mid, last) { let omitLast; if (!pre) { if (mid.s.startsWith('//')) return; if (last.s === ';') { let match = mid.s.match(/&#?[\da-z]+$/i); if (match) { let source = match[0] + last.s; omitLast = this.decodeWikitext(source) === source; } else { omitLast = true; } } else { omitLast = '!,.:?'.includes(last.s) || last.s === ')' && mid.s.includes('('); } } let s = mid.s; if (!omitLast) { s += last.s; } let [midStart, midEnd] = mid.tokenIndices(); this.link( tokens, midStart, omitLast ? midEnd : last.tokenIndices()[1], this.decodeWikitext(s) ); } static headingRe = /^(={1,6})\s*(.+?)\s*(\1)\s*(?=<!--|$)/dg; headingCallback(tokens, pre, mid, post) { if (/{{|<\/?ref(?:\s[^>]*)?>|\[(?:https?:)?\/\/[^\s\[\]]+\]/i.test(mid.s)) return; let s = this.decodeWikitext(mid.s).replace( /'''(.+?)'''|\[\[:?(?:[^|\]]+\|)?([^\]]+)\]\]|<\/?(?:abbr|b|bdi|bdo|big|cite|code|data|del|dfn|em|font|i|ins|kbd|mark|nowiki|q|rb|rp|rt|rtc|ruby|s|samp|small|span|strike|strong|sub|sup|templatestyles|time|translate|tt|u|var)(?:\s[^>]*)?>|<!--.*?-->|\[(?:https?:)?\/\/[^\s\[\]]+\s([^\]]+)\]/gi, '$1$2$3' ).replace(/''(.+?)''/g, '$1').replace(/^[\s_]+|[\s_]+$/g, ''); let t = mw.Title.newFromText( `${!this.isView || !this.isSamePage ? this.getProp() : ''}#${s}` ); if (!t) return; let midIndices = mid.tokenIndices(); if (tokens.slice(...midIndices).some(({ link }) => link)) { this.link(tokens, ...post.tokenIndices(), t); this.link(tokens, ...pre.tokenIndices(), t); } else { this.link(tokens, ...midIndices, t); } } // https://commons.wikimedia.org/wiki/Special:MediaStatistics static galleryRe = /^\s*((?:[^<>\[\]{|}])+\.(?:apng|djv|djvu|flac|gif|jpe|jpeg|jpg|jps|kar|m4a|m4b|m4p|m4r|m4v|mid|midi|mp2|mp3|mp4|mpa|mpe|mpeg|mpg|mpga|oga|ogg|ogm|ogv|ogx|opus|pdf|png|spx|stl|svg|tif|tiff|wav|webm|webp|xcf))\s*(?:\||$)/dgi; galleryCallback(tokens, mid) { let s = this.decodeWikitext(mid.s, true); let t = mw.Title.newFromText(s, 6); if (t && t.getNamespaceId() !== 6) { t = mw.Title.makeTitle(6, s); } if (!t) return; this.link(tokens, ...mid.tokenIndices(), t); } link(tokens, start, end, mwtOrUrl, noRedirect) { let indices = [], last; tokens.slice(start, end).forEach((token, i) => { if (!token.s && !token.link && !token.esc) return; if (token.s && !token.link) { if (!indices.length || last?.link || last?.esc) { indices.push([start + i]); } indices.at(-1)[1] = start + i + 1; } last = token; }); if (indices.some(chunkIndices => chunkIndices.length !== 2)) { mw.notify('Corrupt chunks found'); debugger; } if (!indices.length) return; let attribs = { class: 'smartdiff-link' }, obj; if (typeof mwtOrUrl === 'string') { attribs.class += ' external'; attribs.href = mwtOrUrl; attribs.rel = 'nofollow'; } else { let title = mwtOrUrl.toText(); if (title) { if (Object.hasOwn(this.titles, title)) { obj = this.titles[title]; if (obj.classes) { attribs.class += ' ' + obj.classes.join(' '); } } else { obj = { links: [] }; this.titles[title] = obj; } let fragment; if (obj.url) { attribs.href = obj.url; fragment = mwtOrUrl.getFragment(); } else { let params = obj.red && { action: 'edit', redlink: 1 } || noRedirect && obj.redirect && { redirect: 'no' }; if (obj.canonical) { attribs.href = mw.util.getUrl(obj.canonical, params); fragment = mwtOrUrl.getFragment(); } else { attribs.href = mwtOrUrl.getUrl(params); } } if (fragment) { attribs.href += mw.util.getUrl('#' + fragment); } attribs.title = obj.canonical || title; } else { attribs.class += ' mw-selflink-fragment'; attribs.href = mwtOrUrl.getUrl(); } } let links = indices.reverse().map(chunkIndices => ( this.linkChunk(tokens, ...chunkIndices, attribs) )); if (obj && !obj.processed) { obj.links.push(...links); if (noRedirect) { links.forEach(link => { this.noRedirLinks.add(link); }); } } this.divHasLink = true; } linkChunk(tokens, start, end, attribs) { let newStart = start, newEnd = end; let mid = tokens.slice(start, end); let midTags = mid.filter(token => token.openingTag || token.closingTag); for (let i = 0; ; i += 2) { if (tokens[newStart - 1]?.openingTag && midTags[i]?.closingTag && tokens[newStart - 1].openingTag.tagName === midTags[i].closingTag.tagName ) { midTags.unshift(tokens[newStart - 1]); newStart--; } else { break; } } for (let i = midTags.length - 1; ; i--) { if (tokens[newEnd]?.closingTag && midTags[i]?.openingTag && tokens[newEnd].closingTag.tagName === midTags[i].openingTag.tagName ) { midTags.push(tokens[newEnd]); newEnd++; } else { break; } } if (start - newStart) { console.log(`Moved up ${start - newStart} times`); } if (start - newStart > 1) { mw.notify(`Moved up ${start - newStart} times`); } if (newEnd - end) { console.log(`Moved down ${newEnd - end} times`); } if (newEnd - end > 1) { mw.notify(`Moved down ${newEnd - end} times`); } let link = $('<a>').attr(attribs)[0]; let pre = [{ openingTag: link, link }]; let post = [{ closingTag: link, link }]; if (midTags[0]?.closingTag) { pre.unshift({ ...midTags[0] }); pre.push({ openingTag: midTags[0].closingTag }); } if (midTags.at(-1)?.openingTag) { post.unshift({ closingTag: midTags.at(-1).openingTag }); post.push({ ...midTags.at(-1) }); } tokens.splice(newEnd, 0, ...post); tokens.splice(newStart, 0, ...pre); mid.forEach(token => { if (token.s) { token.link = link; } }); return link; } decodeWikitext(text, decodePercents) { let s = text; if (decodePercents) { try { s = decodeURIComponent(s); } catch {} } return $($.parseHTML(s)).text(); } async getSubpage(s, fallbackNs) { if (await this.canHaveSubpages()) { return mw.Title.newFromText( this.getProp() + s.replace(/\/+$/, '') ); } return mw.Title.newFromText(s, fallbackNs); } async getParentPage(s, fallbackNs) { if (await this.canHaveSubpages()) { let chunks = s.split('/'); let levelCount = chunks.findIndex(v => v !== '..'); let sup = this.getProp().split('/').slice(0, -levelCount).join('/'); if (sup) { let sub = chunks.slice(levelCount).join('/').replace(/\/+$/, ''); return mw.Title.newFromText(sub ? `${sup}/${sub}` : sup); } } return mw.Title.newFromText(s, fallbackNs); } async canHaveSubpages(ns = this.getProp('ns')) { SmartDiff.subNs = SmartDiff.subNs || mw.config.get('wgVisualEditorConfig')?.namespacesWithSubpages || Object.values((await new mw.Api().get({ action: 'query', meta: 'siteinfo', siprop: 'namespaces', formatversion: 2 })).query.namespaces).filter(n => n.subpages).map(n => n.id); return SmartDiff.subNs.includes(ns); } getProp(n = 'pn') { if (this[this.side]) { this.sidePropUsed = !this.isSamePage; return this[this.side][n]; } if (Object.hasOwn(this, n)) { return this[n]; } this.pn = mw.config.get('wgPageName'); this.ns = mw.config.get('wgNamespaceNumber'); return this[n]; } async queryTitles() { let unprocessed = Object.entries(this.titles) .filter(([, v]) => !v.processed).slice(0, 500).map(([k]) => k); while (unprocessed.length) { let curTitles = unprocessed.slice(0, 50); curTitles.forEach(title => { this.titles[title].processed = true; }); let { query } = await new mw.Api().post({ action: 'query', titles: curTitles, iwurl: 1, prop: 'info', inprop: 'linkclasses', inlinkcontext: this.getProp(), formatversion: 2 }, { headers: { 'Promise-Non-Write-API-Action': 1 } }); query.pages?.forEach(p => { let obj = (this.titles[p.title] ??= {}); let classes = p.linkclasses || []; if (p.missing && !p.known) { classes.push('new'); obj.red = true; } else if (p.redirect) { obj.redirect = true; } if (classes.length) { obj.classes = classes; } }); query.interwiki?.forEach(iw => { this.titles[iw.title] = { classes: ['extiw'], url: iw.url }; }); query.normalized?.forEach(({ from, to }) => { this.titles[from] = { ...this.titles[from], ...this.titles[to], canonical: to }; }); curTitles.forEach(title => { let obj = this.titles[title]; if (obj.classes) { $(obj.links).addClass(obj.classes); } if (obj.redirect) { let noRedirLinks = this.noRedirLinks; $(obj.links).attr('href', function () { return mw.util.getUrl( obj.canonical || title, noRedirLinks.has(this) && { redirect: 'no' } ) + this.hash; }); } else { let url = obj.url || obj.red && mw.util.getUrl( obj.canonical || title, { action: 'edit', redlink: 1 } ) || obj.canonical && mw.util.getUrl(obj.canonical); if (url) { $(obj.links).attr('href', function () { return url + this.hash; }); } } if (obj.canonical) { $(obj.links).attr('title', obj.canonical); } obj.links = []; }); unprocessed = unprocessed.slice(50); } } static sds = new WeakMap(); static magicWords = [ '!', '=', 'BASEPAGENAME', 'BASEPAGENAME:', 'BASEPAGENAMEE', 'BASEPAGENAMEE:', 'canonicalurl:', 'CURRENTDAY', 'CURRENTDAY2', 'CURRENTDAYNAME', 'CURRENTDOW', 'CURRENTHOUR', 'CURRENTMONTH', 'CURRENTMONTH1', 'CURRENTMONTHABBREV', 'CURRENTMONTHNAME', 'CURRENTMONTHNAMEGEN', 'CURRENTTIME', 'CURRENTTIMESTAMP', 'CURRENTVERSION', 'CURRENTWEEK', 'CURRENTYEAR', 'DEFAULTCATEGORYSORT:', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DISPLAYTITLE:', 'filepath:', 'formatnum:', 'FULLPAGENAME', 'FULLPAGENAME:', 'FULLPAGENAMEE', 'FULLPAGENAMEE:', 'fullurl:', 'gender:', 'lc:', 'lcfirst:', 'LOCALDAY', 'LOCALDAY2', 'LOCALDAYNAME', 'LOCALDOW', 'LOCALHOUR', 'LOCALMONTH', 'LOCALMONTH1', 'LOCALMONTHABBREV', 'LOCALMONTHNAME', 'LOCALMONTHNAMEGEN', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCALWEEK', 'LOCALYEAR','NAMESPACE', 'NAMESPACE:', 'NAMESPACEE', 'NAMESPACEE:', 'NAMESPACENUMBER', 'NAMESPACENUMBER:', 'ns:', 'NUMBEROFACTIVEUSERS', 'NUMBEROFARTICLES', 'NUMBEROFEDITS', 'NUMBEROFFILES', 'NUMBEROFPAGES', 'NUMBEROFUSERS', 'padleft:', 'PAGENAME', 'PAGENAMEE', 'PAGESINCAT:', 'PAGESINCATEGORY:', 'plural:', 'REVISIONDAY', 'REVISIONDAY:', 'REVISIONDAY2', 'REVISIONDAY2:', 'REVISIONID', 'REVISIONID:', 'REVISIONMONTH', 'REVISIONMONTH:', 'REVISIONMONTH1', 'REVISIONMONTH1:', 'REVISIONSIZE', 'REVISIONTIMESTAMP', 'REVISIONTIMESTAMP:', 'REVISIONUSER', 'REVISIONUSER:', 'REVISIONYEAR', 'REVISIONYEAR:', 'ROOTPAGENAME', 'ROOTPAGENAME:', 'ROOTPAGENAMEE', 'ROOTPAGENAMEE:', 'SHORTDESC:', 'SUBJECTPAGENAME', 'SUBJECTPAGENAME:', 'SUBJECTPAGENAMEE', 'SUBJECTPAGENAMEE:', 'SUBJECTSPACE', 'SUBJECTSPACE:', 'SUBJECTSPACEE', 'SUBJECTSPACEE:', 'SUBPAGENAME', 'SUBPAGENAME:', 'SUBPAGENAMEE', 'SUBPAGENAMEE:', 'TALKPAGENAME', 'TALKPAGENAME:', 'TALKPAGENAMEE', 'TALKPAGENAMEE:', 'TALKSPACE', 'TALKSPACE:', 'TALKSPACEE', 'TALKSPACEE:', 'uc:', 'ucfirst:', 'urlencode:' ]; } if (Array.isArray(window.smartdiffMagicWords)) { SmartDiff.magicWords.push(...window.smartdiffMagicWords); } if (Array.isArray(window.smartdiffTemplates)) { SmartDiff.templates = window.smartdiffTemplates; } mw.hook('wikipage.diff').add((window.sdcb = ($diff => { window.sd = new SmartDiff($diff); }))); mw.hook('wikipage.diff.wikitextBodyUpdate').add((window.sdcbu = ($rows => { let $diff = $rows.closest('.diff'); let sd = SmartDiff.sds.get($diff[0]); if (sd) { sd.init($rows.filter(function () { return this.checkVisibility(); })); } else { window.sd = new SmartDiff($diff); } }))); }); ptd12hqpt5cfpmqwhls0jm506wel0rg MediaWiki:Cite-autoname-template-map.json 8 178994 769780 767221 2026-10-22T19:18:50Z Ahecht 27656 remove AutonameBook 769780 json application/json { "Autoname": [ "*" ] } 3s5qind4027qtuvarv1xqpqjso76mit 769791 769780 2026-10-22T19:40:49Z Ahecht 27656 test 769791 json application/json { "autoname": [ "*" ] } pt2bs92s4ns21zcb3qzoobt7y5fwlgg Template:Autoname 10 179001 769779 768379 2026-10-22T19:16:25Z Ahecht 27656 use autoname function 769779 wikitext text/x-wiki {{safesubst:<noinclude />#invoke:Autoname|autoname}}<noinclude> {{documentation}} </noinclude> twbhkt0s62ibrqnzeszzfxi8dygggg6 Module:Autoname 828 179074 769770 768432 2026-10-22T19:01:26Z Ahecht 27656 Copy from enwiki 769770 Scribunto text/plain local utilities = require ('Module:Citation/CS1/Utilities'); local cfg = mw.loadData ('Module:Citation/CS1/Configuration'); local data = mw.loadData ('Module:Autoname/data/sandbox'); --[[--------------------------< N A M E _ H A S _ E T A L >---------------------------------------------------- Evaluates the content of name parameters (contributor, author, editor) for variations on the theme of et al. If found, the et al. is removed. Adapted from same-named function in Module:Citation/CS1 ]] local function name_has_etal (name) if utilities.is_set (name) then -- name can be nil in which case just return local patterns = cfg.et_al_patterns; -- get patterns from configuration for _, pattern in ipairs (patterns) do -- loop through all of the patterns if name:match (pattern) then -- if this 'et al' pattern is found in name name = name:gsub (pattern, ''); -- remove the offending text return name; -- and done; end end end return name; -- no etal found, return <name> end --[=[-------------------------< G E T _ V _ N A M E _ T A B L E >---------------------------------------------- split apart a |vauthors= or |veditors= parameter. This function allows for corporate names, wrapped in accept- as-written markup to also have commas. Individual author names may be wikilinked. |vauthors=Jones AB, [[E. B. White|White EB]], ((Black, Brown, and Co.)) Adapted from same-named function in Module:Citation/CS1 ]=] local function get_v_name_table (vparam, out_t) local names_t = mw.text.split (vparam, "%s*,%s*"); -- names in vparam are separated by commas local label; -- label from a wikilinked name local i = 1; -- initialize indexer while names_t[i] and i < 5 do -- no more than four names if names_t[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of corporate with one or more commas; this segment has the opening doubled parentheses local name = names_t[i]; i = i + 1; -- bump indexer to next segment while names_t[i] do name = name .. ', ' .. names_t[i]; -- concatenate with previous segments if names_t[i]:match ('^.*%)%)$') then -- if this table member has the closing doubled parentheses break; -- and done reassembling so end i = i + 1; -- bump indexer end table.insert (out_t, name); -- and add corporate name to the output table else local _; _, label, _ = utilities.is_wikilink (names_t[i]); -- wl_type is: 0, no wl (text in <label>); 1, [[D]]; 2, [[L|D]] table.insert (out_t, label); -- add this name end i = i + 1; end return out_t; end --[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >-------------------------------- This function extracts author / editor surnames from |vauthors= or |veditors=. Initials and generational suffixes are discarded. Accept-as-written markup around an individual name is stripped. Adapted from same-named function in Module:Citation/CS1 ]] local function parse_vauthors_veditors (vparam) local names_t = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn= local v_name_table = {}; local last, first, suffix; vparam = name_has_etal (vparam); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period) v_name_table = get_v_name_table (vparam, v_name_table); -- names are separated by commas for i, v_name in ipairs (v_name_table) do first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor local accept_name; v_name, accept_name = utilities.has_accept_as_written (v_name); -- remove accept-this-as-written markup when it wraps all of <v_name> if accept_name then last = v_name; elseif string.find (v_name, "%s") then local lastfirst_t = mw.text.split (v_name, "%s+"); first = table.remove (lastfirst_t); -- removes and returns value of last element in table which should be initials or generational suffix if not mw.ustring.match (first, '^%u+$') then -- mw.ustring here so that later we will catch non-Latin characters suffix = first; -- not initials so assume that whatever we got is a generational suffix first = table.remove (lastfirst_t); -- get what should be the initials from the table end last = table.concat (lastfirst_t, ' '); -- returns a string that is the concatenation of all other names that are not initials and generational suffix if not utilities.is_set (last) then first = ''; -- unset last = v_name; -- last empty because something wrong with first end else last = v_name; -- last name or single corporate name? Doesn't support multiword corporate names? do we need this? end if utilities.is_set (first) then if utilities.is_set (suffix) then suffix = ''; -- unset so we don't add this suffix to all subsequent names end end names_t[i] = last; -- add name to names list end return names_t; -- all done, return list of names end --[[--------------------------< Y E A R _ G E T >-------------------------------------------------------------- because |date= and |publication-date= will be full aliases ofeach other at the next cs1|2 suite update, accept only one of them; assume that |date= is the canonical form ]] local function year_get (args_t) local date, year; local d_dab, y_dab; -- used to identify which to returm when both 'date' and year are set date, d_dab = (args_t['date'] or args_t['publication-date'] or ''):match ('([1-9]%d%d%d?(%l?))'); -- if both are present prefer |date= year, y_dab = (args_t['year'] or ''):match ('([1-9]%d%d%d?(%l?))'); if date and year then if '' ~= d_dab then -- when no CITEREF disambiguator, <d_dab> is empty string return date; -- prefer |date= and |publication-date= over year when 'date' has a CITEREF disambiguator elseif '' ~= y_dab then -- when no CITEREF disambiguator, <y_dab> is empty string return year; -- prefer |year= over 'date' when |year= has a CITEREF disambiguator end end return date or year; -- when no dabs or only one of |date=, |publication-date=, or |year= set end --[[--------------------------< D O M A I N _ G E T >---------------------------------------------------------- extract domain name from a url. ]] local function domain_get (url) url = mw.text.trim (url or '') if url == '' then return nil end local domain = mw.ustring.match(url, "^%a[%w+.-]*://([^/?#]+)") -- Extract the domain (with or without protocol) or mw.ustring.match(url, "^//([^/?#]+)") or mw.ustring.match(url, "^([^/?#]+)") if not domain then return nil end domain = domain:gsub ("^.*@", ""):gsub (":%d+$", "") -- Remove credentials (user:pass@) and port (:8080) local _, segments = domain:gsub ("[^.]+", "") if segments < 2 or domain:find ('%.%.') then -- Reject values that don't look like a domain name return nil elseif segments > 2 then -- Remove common prefixes domain = domain:gsub ("^ww[w%d]%d*%.", ""):gsub ("^m%.", ""):gsub ("^ftp%.", "") end return domain end --[[--------------------------< A U T O N A M E _ M A K E >---------------------------------------------------- common function to create autoname from whichever of contributor / author / editor name list is chosen. ]] local function autoname_make (names_t, year) table.insert (names_t, (year or '') .. '-'); -- add year to name list followed by a hyphen to separate year from ve-added index digit(s) return mw.uri.anchorEncode (table.concat (names_t)); -- concatenate, anchor encode, and done end --[[--------------------------< _ A U T O N A M E >------------------------------------------------------------ entry point from another module or from the debug console ]] local function _autoname (args_t) local names_t = {}; -- sequence to hold values to potentially pass to autoname_make for _, ntype in ipairs (data.params_order_t) do names_t[ntype] = {}; end for param, value in pairs (args_t) do local enum = tonumber (param:match ('%d+')); -- get the enumerator if this parameter has one; nil else local index = param:gsub ('%d+', '#'); local accept; value, accept = utilities.has_accept_as_written (value); -- remove accept-as-written markup if present if not accept then value = name_has_etal (value); end if enum and (5 > enum) then -- sort enumerated name parameter values into the various sequences for _, ntype in ipairs (data.enum_params_order_t) do if data.enum_params_t[ntype][index] then names_t[ntype][enum] = value; break; end end else -- sort non-enumerated name parameter values into the various sequences for _, ntype in ipairs (data.params_order_t) do if data.params_t[ntype][index] then if ntype == 'url' then value = domain_get (value) end names_t[ntype][1] = value; break; end end end if 'vauthors' == param then names_t.author = parse_vauthors_veditors (value); -- fetch a sequence of vauthor surnames elseif 'veditors' == param then names_t.editor = parse_vauthors_veditors (value); -- fetch a sequence of veditor surnames end end local year = year_get (args_t); -- get year portion of date from |date=, |publication-date=, or |year= for _, ntype in ipairs(data.params_order_t) do -- in params_order_t order, make a CITEREF-like anchor for autonaming if names_t[ntype][1] then return autoname_make (names_t[ntype], year); end end end --[[--------------------------< A U T O N A M E >-------------------------------------------------------------- entry point from a template ]] local function autoname (frame) local args_t = require ('Module:Arguments').getArgs (frame); -- get the template's parameters return _autoname (args_t); -- and render the reference name end --[[--------------------------E X P O R T S >------------------------------------------------------------------ ]] return { autoname = autoname, -- entry point from a template _autoname = _autoname, -- entry point from another module or from the debug console } k4n5bsxzytmu18kk5yn5cb0vcrgjyvy 769771 769770 2026-10-22T19:03:06Z Ahecht 27656 don't use sandbox 769771 Scribunto text/plain local utilities = require ('Module:Citation/CS1/Utilities'); local cfg = mw.loadData ('Module:Citation/CS1/Configuration'); local data = mw.loadData ('Module:Autoname/data'); --[[--------------------------< N A M E _ H A S _ E T A L >---------------------------------------------------- Evaluates the content of name parameters (contributor, author, editor) for variations on the theme of et al. If found, the et al. is removed. Adapted from same-named function in Module:Citation/CS1 ]] local function name_has_etal (name) if utilities.is_set (name) then -- name can be nil in which case just return local patterns = cfg.et_al_patterns; -- get patterns from configuration for _, pattern in ipairs (patterns) do -- loop through all of the patterns if name:match (pattern) then -- if this 'et al' pattern is found in name name = name:gsub (pattern, ''); -- remove the offending text return name; -- and done; end end end return name; -- no etal found, return <name> end --[=[-------------------------< G E T _ V _ N A M E _ T A B L E >---------------------------------------------- split apart a |vauthors= or |veditors= parameter. This function allows for corporate names, wrapped in accept- as-written markup to also have commas. Individual author names may be wikilinked. |vauthors=Jones AB, [[E. B. White|White EB]], ((Black, Brown, and Co.)) Adapted from same-named function in Module:Citation/CS1 ]=] local function get_v_name_table (vparam, out_t) local names_t = mw.text.split (vparam, "%s*,%s*"); -- names in vparam are separated by commas local label; -- label from a wikilinked name local i = 1; -- initialize indexer while names_t[i] and i < 5 do -- no more than four names if names_t[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of corporate with one or more commas; this segment has the opening doubled parentheses local name = names_t[i]; i = i + 1; -- bump indexer to next segment while names_t[i] do name = name .. ', ' .. names_t[i]; -- concatenate with previous segments if names_t[i]:match ('^.*%)%)$') then -- if this table member has the closing doubled parentheses break; -- and done reassembling so end i = i + 1; -- bump indexer end table.insert (out_t, name); -- and add corporate name to the output table else local _; _, label, _ = utilities.is_wikilink (names_t[i]); -- wl_type is: 0, no wl (text in <label>); 1, [[D]]; 2, [[L|D]] table.insert (out_t, label); -- add this name end i = i + 1; end return out_t; end --[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >-------------------------------- This function extracts author / editor surnames from |vauthors= or |veditors=. Initials and generational suffixes are discarded. Accept-as-written markup around an individual name is stripped. Adapted from same-named function in Module:Citation/CS1 ]] local function parse_vauthors_veditors (vparam) local names_t = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn= local v_name_table = {}; local last, first, suffix; vparam = name_has_etal (vparam); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period) v_name_table = get_v_name_table (vparam, v_name_table); -- names are separated by commas for i, v_name in ipairs (v_name_table) do first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor local accept_name; v_name, accept_name = utilities.has_accept_as_written (v_name); -- remove accept-this-as-written markup when it wraps all of <v_name> if accept_name then last = v_name; elseif string.find (v_name, "%s") then local lastfirst_t = mw.text.split (v_name, "%s+"); first = table.remove (lastfirst_t); -- removes and returns value of last element in table which should be initials or generational suffix if not mw.ustring.match (first, '^%u+$') then -- mw.ustring here so that later we will catch non-Latin characters suffix = first; -- not initials so assume that whatever we got is a generational suffix first = table.remove (lastfirst_t); -- get what should be the initials from the table end last = table.concat (lastfirst_t, ' '); -- returns a string that is the concatenation of all other names that are not initials and generational suffix if not utilities.is_set (last) then first = ''; -- unset last = v_name; -- last empty because something wrong with first end else last = v_name; -- last name or single corporate name? Doesn't support multiword corporate names? do we need this? end if utilities.is_set (first) then if utilities.is_set (suffix) then suffix = ''; -- unset so we don't add this suffix to all subsequent names end end names_t[i] = last; -- add name to names list end return names_t; -- all done, return list of names end --[[--------------------------< Y E A R _ G E T >-------------------------------------------------------------- because |date= and |publication-date= will be full aliases ofeach other at the next cs1|2 suite update, accept only one of them; assume that |date= is the canonical form ]] local function year_get (args_t) local date, year; local d_dab, y_dab; -- used to identify which to returm when both 'date' and year are set date, d_dab = (args_t['date'] or args_t['publication-date'] or ''):match ('([1-9]%d%d%d?(%l?))'); -- if both are present prefer |date= year, y_dab = (args_t['year'] or ''):match ('([1-9]%d%d%d?(%l?))'); if date and year then if '' ~= d_dab then -- when no CITEREF disambiguator, <d_dab> is empty string return date; -- prefer |date= and |publication-date= over year when 'date' has a CITEREF disambiguator elseif '' ~= y_dab then -- when no CITEREF disambiguator, <y_dab> is empty string return year; -- prefer |year= over 'date' when |year= has a CITEREF disambiguator end end return date or year; -- when no dabs or only one of |date=, |publication-date=, or |year= set end --[[--------------------------< D O M A I N _ G E T >---------------------------------------------------------- extract domain name from a url. ]] local function domain_get (url) url = mw.text.trim (url or '') if url == '' then return nil end local domain = mw.ustring.match(url, "^%a[%w+.-]*://([^/?#]+)") -- Extract the domain (with or without protocol) or mw.ustring.match(url, "^//([^/?#]+)") or mw.ustring.match(url, "^([^/?#]+)") if not domain then return nil end domain = domain:gsub ("^.*@", ""):gsub (":%d+$", "") -- Remove credentials (user:pass@) and port (:8080) local _, segments = domain:gsub ("[^.]+", "") if segments < 2 or domain:find ('%.%.') then -- Reject values that don't look like a domain name return nil elseif segments > 2 then -- Remove common prefixes domain = domain:gsub ("^ww[w%d]%d*%.", ""):gsub ("^m%.", ""):gsub ("^ftp%.", "") end return domain end --[[--------------------------< A U T O N A M E _ M A K E >---------------------------------------------------- common function to create autoname from whichever of contributor / author / editor name list is chosen. ]] local function autoname_make (names_t, year) table.insert (names_t, (year or '') .. '-'); -- add year to name list followed by a hyphen to separate year from ve-added index digit(s) return mw.uri.anchorEncode (table.concat (names_t)); -- concatenate, anchor encode, and done end --[[--------------------------< _ A U T O N A M E >------------------------------------------------------------ entry point from another module or from the debug console ]] local function _autoname (args_t) local names_t = {}; -- sequence to hold values to potentially pass to autoname_make for _, ntype in ipairs (data.params_order_t) do names_t[ntype] = {}; end for param, value in pairs (args_t) do local enum = tonumber (param:match ('%d+')); -- get the enumerator if this parameter has one; nil else local index = param:gsub ('%d+', '#'); local accept; value, accept = utilities.has_accept_as_written (value); -- remove accept-as-written markup if present if not accept then value = name_has_etal (value); end if enum and (5 > enum) then -- sort enumerated name parameter values into the various sequences for _, ntype in ipairs (data.enum_params_order_t) do if data.enum_params_t[ntype][index] then names_t[ntype][enum] = value; break; end end else -- sort non-enumerated name parameter values into the various sequences for _, ntype in ipairs (data.params_order_t) do if data.params_t[ntype][index] then if ntype == 'url' then value = domain_get (value) end names_t[ntype][1] = value; break; end end end if 'vauthors' == param then names_t.author = parse_vauthors_veditors (value); -- fetch a sequence of vauthor surnames elseif 'veditors' == param then names_t.editor = parse_vauthors_veditors (value); -- fetch a sequence of veditor surnames end end local year = year_get (args_t); -- get year portion of date from |date=, |publication-date=, or |year= for _, ntype in ipairs(data.params_order_t) do -- in params_order_t order, make a CITEREF-like anchor for autonaming if names_t[ntype][1] then return autoname_make (names_t[ntype], year); end end end --[[--------------------------< A U T O N A M E >-------------------------------------------------------------- entry point from a template ]] local function autoname (frame) local args_t = require ('Module:Arguments').getArgs (frame); -- get the template's parameters return _autoname (args_t); -- and render the reference name end --[[--------------------------E X P O R T S >------------------------------------------------------------------ ]] return { autoname = autoname, -- entry point from a template _autoname = _autoname, -- entry point from another module or from the debug console } knh1qwaej6awgek0xp5tyhfkzwvam2v 769781 769771 2026-10-22T19:27:25Z Ahecht 27656 slightly more efficient since we don't need to overwrite the value of value 769781 Scribunto text/plain local utilities = require ('Module:Citation/CS1/Utilities'); local cfg = mw.loadData ('Module:Citation/CS1/Configuration'); local data = mw.loadData ('Module:Autoname/data'); --[[--------------------------< N A M E _ H A S _ E T A L >---------------------------------------------------- Evaluates the content of name parameters (contributor, author, editor) for variations on the theme of et al. If found, the et al. is removed. Adapted from same-named function in Module:Citation/CS1 ]] local function name_has_etal (name) if utilities.is_set (name) then -- name can be nil in which case just return local patterns = cfg.et_al_patterns; -- get patterns from configuration for _, pattern in ipairs (patterns) do -- loop through all of the patterns if name:match (pattern) then -- if this 'et al' pattern is found in name name = name:gsub (pattern, ''); -- remove the offending text return name; -- and done; end end end return name; -- no etal found, return <name> end --[=[-------------------------< G E T _ V _ N A M E _ T A B L E >---------------------------------------------- split apart a |vauthors= or |veditors= parameter. This function allows for corporate names, wrapped in accept- as-written markup to also have commas. Individual author names may be wikilinked. |vauthors=Jones AB, [[E. B. White|White EB]], ((Black, Brown, and Co.)) Adapted from same-named function in Module:Citation/CS1 ]=] local function get_v_name_table (vparam, out_t) local names_t = mw.text.split (vparam, "%s*,%s*"); -- names in vparam are separated by commas local label; -- label from a wikilinked name local i = 1; -- initialize indexer while names_t[i] and i < 5 do -- no more than four names if names_t[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of corporate with one or more commas; this segment has the opening doubled parentheses local name = names_t[i]; i = i + 1; -- bump indexer to next segment while names_t[i] do name = name .. ', ' .. names_t[i]; -- concatenate with previous segments if names_t[i]:match ('^.*%)%)$') then -- if this table member has the closing doubled parentheses break; -- and done reassembling so end i = i + 1; -- bump indexer end table.insert (out_t, name); -- and add corporate name to the output table else local _; _, label, _ = utilities.is_wikilink (names_t[i]); -- wl_type is: 0, no wl (text in <label>); 1, [[D]]; 2, [[L|D]] table.insert (out_t, label); -- add this name end i = i + 1; end return out_t; end --[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >-------------------------------- This function extracts author / editor surnames from |vauthors= or |veditors=. Initials and generational suffixes are discarded. Accept-as-written markup around an individual name is stripped. Adapted from same-named function in Module:Citation/CS1 ]] local function parse_vauthors_veditors (vparam) local names_t = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn= local v_name_table = {}; local last, first, suffix; vparam = name_has_etal (vparam); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period) v_name_table = get_v_name_table (vparam, v_name_table); -- names are separated by commas for i, v_name in ipairs (v_name_table) do first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor local accept_name; v_name, accept_name = utilities.has_accept_as_written (v_name); -- remove accept-this-as-written markup when it wraps all of <v_name> if accept_name then last = v_name; elseif string.find (v_name, "%s") then local lastfirst_t = mw.text.split (v_name, "%s+"); first = table.remove (lastfirst_t); -- removes and returns value of last element in table which should be initials or generational suffix if not mw.ustring.match (first, '^%u+$') then -- mw.ustring here so that later we will catch non-Latin characters suffix = first; -- not initials so assume that whatever we got is a generational suffix first = table.remove (lastfirst_t); -- get what should be the initials from the table end last = table.concat (lastfirst_t, ' '); -- returns a string that is the concatenation of all other names that are not initials and generational suffix if not utilities.is_set (last) then first = ''; -- unset last = v_name; -- last empty because something wrong with first end else last = v_name; -- last name or single corporate name? Doesn't support multiword corporate names? do we need this? end if utilities.is_set (first) then if utilities.is_set (suffix) then suffix = ''; -- unset so we don't add this suffix to all subsequent names end end names_t[i] = last; -- add name to names list end return names_t; -- all done, return list of names end --[[--------------------------< Y E A R _ G E T >-------------------------------------------------------------- because |date= and |publication-date= will be full aliases ofeach other at the next cs1|2 suite update, accept only one of them; assume that |date= is the canonical form ]] local function year_get (args_t) local date, year; local d_dab, y_dab; -- used to identify which to returm when both 'date' and year are set date, d_dab = (args_t['date'] or args_t['publication-date'] or ''):match ('([1-9]%d%d%d?(%l?))'); -- if both are present prefer |date= year, y_dab = (args_t['year'] or ''):match ('([1-9]%d%d%d?(%l?))'); if date and year then if '' ~= d_dab then -- when no CITEREF disambiguator, <d_dab> is empty string return date; -- prefer |date= and |publication-date= over year when 'date' has a CITEREF disambiguator elseif '' ~= y_dab then -- when no CITEREF disambiguator, <y_dab> is empty string return year; -- prefer |year= over 'date' when |year= has a CITEREF disambiguator end end return date or year; -- when no dabs or only one of |date=, |publication-date=, or |year= set end --[[--------------------------< D O M A I N _ G E T >---------------------------------------------------------- extract domain name from a url. ]] local function domain_get (url) url = mw.text.trim (url or '') if url == '' then return nil end local domain = mw.ustring.match(url, "^%a[%w+.-]*://([^/?#]+)") -- Extract the domain (with or without protocol) or mw.ustring.match(url, "^//([^/?#]+)") or mw.ustring.match(url, "^([^/?#]+)") if not domain then return nil end domain = domain:gsub ("^.*@", ""):gsub (":%d+$", "") -- Remove credentials (user:pass@) and port (:8080) local _, segments = domain:gsub ("[^.]+", "") if segments < 2 or domain:find ('%.%.') then -- Reject values that don't look like a domain name return nil elseif segments > 2 then -- Remove common prefixes domain = domain:gsub ("^ww[w%d]%d*%.", ""):gsub ("^m%.", ""):gsub ("^ftp%.", "") end return domain end --[[--------------------------< A U T O N A M E _ M A K E >---------------------------------------------------- common function to create autoname from whichever of contributor / author / editor name list is chosen. ]] local function autoname_make (names_t, year) table.insert (names_t, (year or '') .. '-'); -- add year to name list followed by a hyphen to separate year from ve-added index digit(s) return mw.uri.anchorEncode (table.concat (names_t)); -- concatenate, anchor encode, and done end --[[--------------------------< _ A U T O N A M E >------------------------------------------------------------ entry point from another module or from the debug console ]] local function _autoname (args_t) local names_t = {}; -- sequence to hold values to potentially pass to autoname_make for _, ntype in ipairs (data.params_order_t) do names_t[ntype] = {}; end for param, value in pairs (args_t) do local enum = tonumber (param:match ('%d+')); -- get the enumerator if this parameter has one; nil else local index = param:gsub ('%d+', '#'); local accept; value, accept = utilities.has_accept_as_written (value); -- remove accept-as-written markup if present if not accept then value = name_has_etal (value); end if enum and (5 > enum) then -- sort enumerated name parameter values into the various sequences for _, ntype in ipairs (data.enum_params_order_t) do if data.enum_params_t[ntype][index] then names_t[ntype][enum] = value; break; end end else -- sort non-enumerated name parameter values into the various sequences for _, ntype in ipairs (data.params_order_t) do if data.params_t[ntype][index] then if ntype == 'url' then names_t[ntype][1] = domain_get (value); else names_t[ntype][1] = value; end break; end end end if 'vauthors' == param then names_t.author = parse_vauthors_veditors (value); -- fetch a sequence of vauthor surnames elseif 'veditors' == param then names_t.editor = parse_vauthors_veditors (value); -- fetch a sequence of veditor surnames end end local year = year_get (args_t); -- get year portion of date from |date=, |publication-date=, or |year= for _, ntype in ipairs(data.params_order_t) do -- in params_order_t order, make a CITEREF-like anchor for autonaming if names_t[ntype][1] then return autoname_make (names_t[ntype], year); end end end --[[--------------------------< A U T O N A M E >-------------------------------------------------------------- entry point from a template ]] local function autoname (frame) local args_t = require ('Module:Arguments').getArgs (frame); -- get the template's parameters return _autoname (args_t); -- and render the reference name end --[[--------------------------E X P O R T S >------------------------------------------------------------------ ]] return { autoname = autoname, -- entry point from a template _autoname = _autoname, -- entry point from another module or from the debug console } pinn999ka3q8x82mka69q5cldqsblfs User:Phoenix3452/sandbox 2 179413 769761 769490 2026-10-22T13:45:10Z Phoenix3452 76309 769761 wikitext text/x-wiki <div style="background:linear-gradient(145deg,#130606,#35100a,#170707);border:3px solid #ff5722;border-radius:16px;padding:22px;color:#ffe4c4;font-family:sans-serif;"> <div style="text-align:center;background:linear-gradient(120deg,#200606,#78200b,#200606);border:2px solid #ff762e;border-radius:12px;padding:25px 10px;"> <div style="font-size:36px;font-weight:bold;color:#ff792f;text-shadow:0 0 12px #ff2600;"> 🔥🐦‍🔥 PHOENIX SANDBOX 🐦‍🔥🔥 </div> <div style="font-size:14px;letter-spacing:3px;color:#ffd0a0;margin-top:10px;"> EXPERIMENT · CREATE · RISE </div> </div> <div style="text-align:center;margin:25px 0 12px;font-size:24px;font-weight:bold;color:#ff762e;"> ⚔️ WELCOME TO THE WORKSHOP </div> <div style="background:#251010;border:1px solid #c94725;border-radius:10px;padding:18px;line-height:1.8;"> Welcome to my Phoenix Sandbox! This is my personal testing area for experimenting with wiki markup, formatting, templates, layouts, and new ideas before using them elsewhere. 🔥 **Feel free to experiment, make mistakes, and learn.** </div> <div style="text-align:center;margin:25px 0 12px;font-size:23px;font-weight:bold;color:#ff762e;"> 🛠️ TESTING ZONE </div> <div style="background:#1b0909;border:1px solid #87351d;border-radius:10px;padding:18px;"> <div style="color:#ffb16e;font-size:18px;font-weight:bold;"> 📌 Current experiments </div> * 🔥 Testing custom colors and borders * 🐦‍🔥 Building Phoenix-themed layouts * ⚔️ Practicing wiki markup * 👑 Designing new user-page features * 🛡️ Testing templates and navigation </div> <div style="text-align:center;margin:25px 0 12px;font-size:23px;font-weight:bold;color:#ff762e;"> 📚 USEFUL LINKS </div> <div style="text-align:center;background:#200909;border:1px solid #87351d;border-radius:10px;padding:14px;"> <div style="display:inline-block;background:#76200e;border:2px solid #ff762e;border-radius:8px;padding:10px;margin:5px;"> [[Special:MyPage|🏠 HOME PAGE]] </div> <div style="display:inline-block;background:#76200e;border:2px solid #ff762e;border-radius:8px;padding:10px;margin:5px;"> [[User talk:{{PAGENAME}}|💬 MY TALK PAGE]] </div> <div style="display:inline-block;background:#76200e;border:2px solid #ff762e;border-radius:8px;padding:10px;margin:5px;"> [[Special:MyPage/sandbox|🛠️ MY SANDBOX]] </div> </div> <div style="text-align:center;margin-top:25px;padding:18px;border-top:2px solid #ff5722;color:#ff9966;"> <div style="font-size:22px;font-weight:bold;"> 🐦‍🔥 FROM ASHES TO CREATION 🔥 </div> <div style="font-size:13px;margin-top:8px;"> EVERY GREAT IDEA STARTS SOMEWHERE. </div> </div> 15jpv86yazcysge6nzh4ok99pvor3vh All Eyes on Me (mixtape) 0 179418 769789 769502 2026-10-22T19:38:29Z Jaheim Ember 76112 769789 wikitext text/x-wiki {{Use mdy dates|date=December 2011}} {{Infobox album | name = All Eyes on Me | type = [[Studio mixtape]] | artist = [[Nicky Jam]] | cover = | alt = | released = {{Start date|2001|02|13}} | recorded = October – December 2000 | studio = Meth Row Studios | genre = * [[Puerto Rican hip-hop]] * [[latin hip-hop]] * [[reggaeton rap]] * [[G-funk]] | length = | label = {{hlist|[[Meth Row Records|Meth Row]]|[[Interscope Records|Interscope]]}} | producer = * Nicky Jam * Rob the Viking * [[Denine Porter]] * [[Donnie Wahlberg]] * [[The Alchemist (musician)|The Alchemist]] * [[Erick Onasis (musician)|Erick Onasis]] * [[Evidence (musician)|Evidence]] * [[Jermaine Dupri]] * [[DJ Muggs]] * [[DJ Lethal]] * [[Todd Ray|T-Ray]] * [[Everlast]] | prev_title = [[...Distinto a los demás]] | prev_year = 1995 | next_title = [[Haciendo escante]] | next_year = 2001 | misc = {{Singles | name = All Eyes on Me | type = [[Studio mixtape]] | single1 = [[Dear Mama (Nicky Jam song)|Dear Mama]] | single1date = December 3, 2000 | single2 = [[Changes (Nicky Jam song)|Changes]] | single2date = May 7, 2001 | single3 = [[To Live and Die in L.A. (Nicky Jam song)|To Live and Die in L.A.]] | single3date = June 4, 2001 | single4 = [[Hail Mary (Nicky Jam song)|Hail Mary]] | single4date = September 15, 2001 }} }} '''''All Eyes on Me''''' is a [[studio mixtape]] by American [[reggaeton]] rapper [[Nicky Jam]]. It was released on February 13, 2001, by [[Meth Row Records]] and [[Interscope Records]]. {{Nicky Jam}} {{Authority control}} [[Category:2001 mixtape albums]] [[Category:Albums produced by Denine Porter]] [[Category:Albums produced by Jermaine Dupri]] [[Category:Albums produced by The Alchemist (musician)]] [[Category:Albums produced by Everlast]] [[Category:Meth Row Records mixtape albums]] [[Category:Interscope Records mixtape albums]] [[Category:Nicky Jam mixtape albums]] [[Category:Albums produced by Erick Onasis (musician)]] [[Category:Studio mixtape albums]] [[Category:G-funk albums]] [[Category:Albums produced by DJ Muggs]] pxjz6h728u0em7mmbdjz7zque28pv2k Wikipedia:Requests/Permissions/CKlimas-WMF 4 179423 769749 769614 2026-10-22T12:41:54Z CKlimas-WMF 75493 /* CKlimas-WMF */ Reply 769749 wikitext text/x-wiki <!--@Bureaucrats: If you close this request as {{Done}} add {{Request-done|1=~~~~|2=Closing rationale}} to the top of the page. If you close it as {{Not done}}, add {{Request-not done|1=~~~~|2=Closing rationale}} there, then close with {{Request closed}}.--> === [[User:CKlimas-WMF|CKlimas-WMF]] === * {{User3|CKlimas-WMF}}, [[Special:CentralAuth/CKlimas-WMF|global contribs]] 21:29, 21 October 2026 (UTC) * '''Motive for request:''' I'm a Wikimedia Foundation employee working on https://phabricator.wikimedia.org/T441511 and want to create a new system message at https://test.wikipedia.org/wiki/MediaWiki:CentralNoticeAppsCommsEvents_crossPlatform.js, but the page tells me that I don't have permission to do so. My goal is to test JavaScript code that will simplify banners that direct people to the Wikipedia mobile apps. * '''Requested rights:''' I think I need administrator rights to do the above, but I'd be happy to have fewer permissions if it's possible to add a new system message with a different role. * '''Comments:''' @[[User:CKlimas-WMF]] please reach out to WMF T&S for staff permissions per [[:wmf:Policy:Wikimedia Foundation Staff Userrights Policy]] (the same policy is also published on officewiki). --[[User:Johannnes89|Johannnes89]] ([[User talk:Johannnes89|talk]]) 10:02, 22 October 2026 (UTC) *:Appreciate the pointer! [[User:CKlimas-WMF|CKlimas-WMF]] ([[User talk:CKlimas-WMF|talk]]) 12:41, 22 October 2026 (UTC) <!-- DO NOT FORGET to transclude your request at THE TOP of [[Wikipedia:Requests/Permissions]] or nobody will see it! --> [[Category:!Requests]] [[Category:Really big category]] __NOINDEX__ 3yeud71zboz5x9bdmtuzubr1tv3rfqp User:Phoenix3452/common.js 2 179435 769739 2026-10-22T12:16:00Z Phoenix3452 76309 create my first bot script 769739 javascript text/javascript /** * My first Test Wikipedia bot * Version 1: safe connection test */ mw.loader.using(['mediawiki.api']).then(function () { var api = new mw.Api(); mw.notify('My bot script has loaded!', { title: 'Test Wikipedia Bot' }); console.log('My bot is ready!'); }); 97lwmr8mpvx61itby01ff22ygym7ny2 769740 769739 2026-10-22T12:18:08Z Phoenix3452 76309 769740 javascript text/javascript /** * My Test Wikipedia Bot * Version 2: one-click test edit */ mw.loader.using(['mediawiki.api']).then(function () { var api = new mw.Api(); // Do not add the control panel twice. if (document.getElementById('my-test-bot-panel')) { return; } // Create the control panel. var panel = document.createElement('div'); panel.id = 'my-test-bot-panel'; panel.style.cssText = 'padding:12px;margin:12px 0;border:2px solid #36c;' + 'border-radius:8px;background:#f0f6ff;color:#202122;'; var heading = document.createElement('h3'); heading.textContent = 'My Test Wikipedia Bot'; var description = document.createElement('p'); description.textContent = 'Click the button below to add one test message to your own bot sandbox.'; var button = document.createElement('button'); button.textContent = 'Make one test edit'; button.style.cssText = 'padding:8px 12px;cursor:pointer;'; var status = document.createElement('p'); status.textContent = 'Bot ready. No edits have been made.'; panel.append(heading, description, button, status); var content = document.getElementById('mw-content-text'); if (!content) { return; } content.prepend(panel); button.addEventListener('click', function () { var username = mw.config.get('wgUserName'); if (!username) { status.textContent = 'Please log in first.'; return; } var target = 'User:' + username + '/Bot sandbox'; if (!confirm( 'Your bot will append one test message to ' + target + '. Continue?' )) { return; } button.disabled = true; status.textContent = 'Making your test edit...'; var message = '\n* Bot test successful! Timestamp: ' + new Date().toISOString() + '\n'; api.postWithToken('csrf', { action: 'edit', title: target, appendtext: message, summary: 'Testing my first browser bot', formatversion: '2' }).then(function (data) { if (data.edit && data.edit.result === 'Success') { status.textContent = 'Success! Your test edit was saved.'; window.open( mw.util.getUrl(target), '_blank', 'noopener' ); } else { status.textContent = 'The wiki did not confirm the edit. Please check the page.'; } }).catch(function (error) { status.textContent = 'Edit failed: ' + String(error); }).then(function () { button.disabled = false; }); }); mw.notify('Your bot control panel is ready!', { title: 'Test Wikipedia Bot' }); }); otrekk24kgf68l5q4vuysjjfvb11xh5 769751 769740 2026-10-22T12:46:09Z Phoenix3452 76309 Blanked the page 769751 javascript text/javascript phoiac9h4m842xq45sp7s6u21eteeq1 User:Phoenix3452/Bot sandbox 2 179436 769741 2026-10-22T12:18:52Z Phoenix3452 76309 Testing my first browser bot 769741 wikitext text/x-wiki * Bot test successful! Timestamp: 2026-10-22T12:18:52.336Z 5xsosk3iwfn7rf2olfayqcqbl9549al 769742 769741 2026-10-22T12:19:06Z Phoenix3452 76309 Testing my first browser bot 769742 wikitext text/x-wiki * Bot test successful! Timestamp: 2026-10-22T12:18:52.336Z * Bot test successful! Timestamp: 2026-10-22T12:19:06.504Z c85sck97zck499aw8j314uqasghdzpf 769743 769742 2026-10-22T12:25:07Z Phoenix3452 76309 Testing my first browser bot 769743 wikitext text/x-wiki * Bot test successful! Timestamp: 2026-10-22T12:18:52.336Z * Bot test successful! Timestamp: 2026-10-22T12:19:06.504Z * Bot test successful! Timestamp: 2026-10-22T12:25:07.259Z 9770b857sz56f7ocjo3i7vjgwgm0jlw 769744 769743 2026-10-22T12:25:21Z Phoenix3452 76309 Blanked the page 769744 wikitext text/x-wiki phoiac9h4m842xq45sp7s6u21eteeq1 769747 769744 2026-10-22T12:34:26Z Phoenix3452 76309 Testing my first browser bot 769747 wikitext text/x-wiki * Bot test successful! Timestamp: 2026-10-22T12:34:25.791Z dc6ackg89yh9zynzq0leolzddcdgrze 769750 769747 2026-10-22T12:44:04Z Phoenix3452 76309 Testing my first browser bot 769750 wikitext text/x-wiki * Bot test successful! Timestamp: 2026-10-22T12:34:25.791Z * Bot test successful! Timestamp: 2026-10-22T12:44:04.613Z ksqwe2g0cqs09cgo88nqqwmlqpslub0 User:Phoenix3452/Bot userpage 2 179437 769745 2026-10-22T12:26:28Z Phoenix3452 76309 Created page with "{{db-userreq}}" 769745 wikitext text/x-wiki {{db-userreq}} cxh87nhjk77iqiazvexez2i2s1q88jr 769746 769745 2026-10-22T12:27:31Z Phoenix3452 76309 769746 wikitext text/x-wiki {{db-userreq}} {{retired|bot=yes}} t3z81hwolmly5o8e9500l6brkp355qb 769748 769746 2026-10-22T12:35:07Z Phoenix3452 76309 769748 wikitext text/x-wiki {{db-userreq}} {{retired|bot=yes}} {{db-g7}} jn0t7kvifx8d59pjy1rnhcttay9ivt3 User:John Vandenberg/createonly/1792674370.157437 2 179438 769756 2026-10-22T13:06:19Z Pywikibot-test 23124 Pywikibot 11.10.0.dev0 769756 wikitext text/x-wiki phoiac9h4m842xq45sp7s6u21eteeq1 Wikipedia:Requests/Permissions/Phoenix3452 4 179439 769763 2026-10-22T14:18:54Z Phoenix3452 76309 Created page with "<!--@Bureaucrats: If you close this request as {{Done}} add {{Request-done|1=~~~~|2=Closing rationale}} to the top of the page. If you close it as {{Not done}}, add {{Request-not done|1=~~~~|2=Closing rationale}} there, then close with {{Request closed}}.--> === [[User:{{subst:REVISIONUSER}}|{{subst:REVISIONUSER}}]] === * {{User3|{{subst:REVISIONUSER}}}}, [[Special:CentralAuth/{{subst:REVISIONUSER}}|global contribs]] ~~~~~ * '''Motive for request:''' hello, i am looking..." 769763 wikitext text/x-wiki <!--@Bureaucrats: If you close this request as {{Done}} add {{Request-done|1=~~~~|2=Closing rationale}} to the top of the page. If you close it as {{Not done}}, add {{Request-not done|1=~~~~|2=Closing rationale}} there, then close with {{Request closed}}.--> === [[User:Phoenix3452|Phoenix3452]] === * {{User3|Phoenix3452}}, [[Special:CentralAuth/Phoenix3452|global contribs]] 14:18, 22 October 2026 (UTC) * '''Motive for request:''' hello, i am looking to test administrator capabilities regarding anti-vandalism and spam mitigaton workflows ( such as page deletion revision deletion user blocking etc.) Thank you! [[User:Phoenix3452|<span style="color:#ff6a00;">🔥🐦‍🔥 Phoenix</span>]] ([[User talk:Phoenix3452|<span style="color:#cc3300;">⚔️ Mentor Talk 🔥</span>]]) 14:18, 22 October 2026 (UTC) * '''Requested rights:''' administrator * '''Comments:''' <!-- Comments of other users --> <!-- DO NOT FORGET to transclude your request at THE TOP of [[Wikipedia:Requests/Permissions]] or nobody will see it! --> [[Category:!Requests]] [[Category:Really big category]] __NOINDEX__ ce0z9dyx1sm1886ak6ys8pg1wubemx0 Module:Autoname/data 828 179440 769772 2026-10-22T19:03:56Z Ahecht 27656 copy from enwiki 769772 Scribunto text/plain local cfg = mw.loadData ('Module:Citation/CS1/Configuration'); --[[--------------------------< B A S E _ P A R A M E T E R S >------------------------------------------------ ]] local param_alias_keys_t = { -- These values represent keys in the [[Module:Citation/CS1/Configuration]] aliases table ['author'] = 'AuthorList-Last', ['contributor'] = 'ContributorList-Last', ['editor'] = 'EditorList-Last', ['periodical'] = 'Periodical', ['encyclopedia'] = 'Encyclopedia', ['title'] = 'Title', ['booktitle'] = 'BookTitle', --{{cite conference}} only ['url'] = 'URL' }; local params_order_t = { -- the order to evaluate non-enumerated parameters; also order to evaluate params for final rendering 'contributor', -- contributors are always first 'author', 'editor', 'periodical', 'encyclopedia', 'title', 'booktitle', -- {{cite conference}} only 'url' -- url is always last }; --[[--------------------------< E N U M E R A T E D _ N A M E L I S T _ P A R A M E T E R S >------------------ ]] local enum_param_alias_keys_t = { -- These values represent keys in the [[Module:Citation/CS1/Configuration]] aliases table ['author'] = 'AuthorList-Last', ['contributor'] = 'ContributorList-Last', ['editor'] = 'EditorList-Last', } local enum_params_order_t = { -- the order to evaluate enumerated parameters 'contributor', -- contributors are always first 'author', 'editor' }; --[[--------------------------< F E T C H P A R A M E T E R A L I A S E S >-------------------------------- ]] local params_t = {}; -- sequences to hold the various name parameter values local enum_params_t = {}; for k,v in pairs (param_alias_keys_t) do -- fetch parameter names and aliases in /data from [[Module:Citation/CS1/Configuration]] params_t[k] = {} if type(cfg.aliases[v]) == 'table' then for _, alias in ipairs (cfg.aliases[v]) do params_t[k][alias:gsub('#', '')] = true end else params_t[k][cfg.aliases[v]:gsub('#', '')] = true end end for k,v in pairs (enum_param_alias_keys_t) do enum_params_t[k] = {} if type(cfg.aliases[v]) == 'table' then for _, alias in ipairs (cfg.aliases[v]) do enum_params_t[k][alias] = true end else enum_params_t[k][cfg.aliases[v]] = true end end --[[--------------------------< E X P O R T S >---------------------------------------------------------------- ]] return { params_t = params_t, enum_params_t = enum_params_t, params_order_t = params_order_t, enum_params_order_t = enum_params_order_t, } o3gmdnp0kgf3bannih7ub1kgrfjsi0z MediaWiki:Visualeditor-cite-tool-name-book 8 179441 769773 2026-10-22T19:04:06Z Ahecht 27656 {{#invoke:Autoname|autoname}} 769773 wikitext text/x-wiki {{#invoke:Autoname|autoname}} 74huxy9kzywgqcqg6zae2c6xz3x9axn 769774 769773 2026-10-22T19:08:51Z Ahecht 27656 revert 769774 wikitext text/x-wiki Book st3dea9d32cu4s6ds8flmm2qi4o9886 User:Ahecht/sandbox 2 179443 769776 2026-10-22T19:10:35Z Ahecht 27656 create 769776 wikitext text/x-wiki <ref>{{Cite book |title=The New encyclopaedia Britannica |date=1993 |publisher=Encyclopaedia Britannica |isbn=978-0-85229-571-7 |editor-last=Encyclopaedia Britannica, Inc |edition=15th ed |location=Chicago}}</ref> <ref>{{Cite book |last=Adams |first=Douglas |title=The hitchhiker's guide to the galaxy |date=2009 |publisher=Ballantine Books |isbn=978-0-345-41891-3 |edition=Del Rey trade pbk. ed |location=New York}}</ref> <ref>{{Cite book |title=Foo |isbn=123456789}}</ref> <ref>{{Cite book |title= |isbn=123456789}}</ref> bwbv65fng22ueoerxbx41tbui1tlxxv 769777 769776 2026-10-22T19:11:02Z Ahecht 27656 fix 769777 wikitext text/x-wiki <ref>{{Cite book |title=The New encyclopaedia Britannica |date=1993 |publisher=Encyclopaedia Britannica |isbn=978-0-85229-571-7 |editor-last=Encyclopaedia Britannica, Inc |edition=15th |location=Chicago}}</ref> <ref>{{Cite book |last=Adams |first=Douglas |title=The hitchhiker's guide to the galaxy |date=2009 |publisher=Ballantine Books |isbn=978-0-345-41891-3 |location=New York}}</ref> <ref>{{Cite book |title=Foo |isbn=123456789}}</ref> <ref>{{Cite book |title= |isbn=123456789}}</ref> 5uw0nf5hb1ypko7l57g96iigkr9roh5 All Eyes on Me 0 179444 769783 2026-10-22T19:33:44Z Jaheim Ember 76112 Created page with "'''All Eyes on Me''' may refer to: * [[All Eyes on Me (AKA song)|"All Eyes on Me" (AKA song)]], 2014 single by South African rapper AKA * [[All Eyes on Me (Bo Burnham song)|"All Eyes on Me" (Bo Burnham song)]], 2021 * [[All Eyes on Me (Jisoo song)|"All Eyes on Me" (Jisoo song)]], 2023 single by Jisoo * "All Eyes on Me", 2022 song from the album ''[[Alpha Zulu]]'' by Phoenix * "All Eyes on Me", 1998 song from the album ''[[Dizzy Up the Girl]]'' by the Goo Goo Dolls * "Al..." 769783 wikitext text/x-wiki '''All Eyes on Me''' may refer to: * [[All Eyes on Me (AKA song)|"All Eyes on Me" (AKA song)]], 2014 single by South African rapper AKA * [[All Eyes on Me (Bo Burnham song)|"All Eyes on Me" (Bo Burnham song)]], 2021 * [[All Eyes on Me (Jisoo song)|"All Eyes on Me" (Jisoo song)]], 2023 single by Jisoo * "All Eyes on Me", 2022 song from the album ''[[Alpha Zulu]]'' by Phoenix * "All Eyes on Me", 1998 song from the album ''[[Dizzy Up the Girl]]'' by the Goo Goo Dolls * "All Eyes on Me", 2006 song from the album ''[[LeToya (album)|LeToya]]'' by [[LeToya Luckett]], featuring [[Paul Wall]] * "All Eyes on Me", 2007 song from the album ''[[Food (Zico Chain album)|Food]]'' by Zico Chain * "All Eyes on Me", 2009 song from the album ''[[Til the Casket Drops (Clipse album)|Til the Casket Drops]]'' by [[Clipse]], featuring [[Keri Hilson]] * ''All Eyes on Me'', 2018 extended play release by [[Conro]] ==See also== * "[[All Eyes on You]]", a 2015 song by Meek Mill from the album ''Dreams Worth More Than Money'' * "All Eyes on You", a 1982 song by Peter Frampton from the album [[Premonition (Peter Frampton album)|''Premonition'' (Peter Frampton album)]] * {{intitle}} * [[All Eyez on Me (disambiguation)]] * [[Eyes on Me (disambiguation)]] {{disambig}} p1crig41rqexf0e4fzrod1jkdkvwiyv 769787 769783 2026-10-22T19:37:19Z Jaheim Ember 76112 769787 wikitext text/x-wiki '''All Eyes on Me''' may refer to: * [[All Eyes on Me (mixtape)|''All Eyes on Me'' (mixtape)]], 2001 studio mixtape by Nicky Jam * [[All Eyes on Me (AKA song)|"All Eyes on Me" (AKA song)]], 2014 single by South African rapper AKA * [[All Eyes on Me (Bo Burnham song)|"All Eyes on Me" (Bo Burnham song)]], 2021 * [[All Eyes on Me (Jisoo song)|"All Eyes on Me" (Jisoo song)]], 2023 single by Jisoo * "All Eyes on Me", 2022 song from the album ''[[Alpha Zulu]]'' by Phoenix * "All Eyes on Me", 1998 song from the album ''[[Dizzy Up the Girl]]'' by the Goo Goo Dolls * "All Eyes on Me", 2006 song from the album ''[[LeToya (album)|LeToya]]'' by [[LeToya Luckett]], featuring [[Paul Wall]] * "All Eyes on Me", 2007 song from the album ''[[Food (Zico Chain album)|Food]]'' by Zico Chain * "All Eyes on Me", 2009 song from the album ''[[Til the Casket Drops (Clipse album)|Til the Casket Drops]]'' by [[Clipse]], featuring [[Keri Hilson]] * ''All Eyes on Me'', 2018 extended play release by [[Conro]] ==See also== * "[[All Eyes on You]]", a 2015 song by Meek Mill from the album ''Dreams Worth More Than Money'' * "All Eyes on You", a 1982 song by Peter Frampton from the album [[Premonition (Peter Frampton album)|''Premonition'' (Peter Frampton album)]] * {{intitle}} * [[All Eyez on Me (disambiguation)]] * [[Eyes on Me (disambiguation)]] {{disambig}} rqwieadd7xcoi5jgny8r20x0dzmmfe9 All Eyes on Me (disambiguation) 0 179445 769785 2026-10-22T19:34:36Z Jaheim Ember 76112 Redirected page to [[All Eyes on Me]] 769785 wikitext text/x-wiki #REDIRECT [[All Eyes on Me]] {{Redirect category shell| {{R to disambiguation page}} }} 5269wc5vyepql408i97j80tm1iqbvd4 Category:Interscope Records mixtape albums 14 179446 769790 2026-10-22T19:39:16Z Jaheim Ember 76112 Created page with "[[Category:Interscope Records albums| Mixtape]] [[Category:Mixtape albums by record label]]" 769790 wikitext text/x-wiki [[Category:Interscope Records albums| Mixtape]] [[Category:Mixtape albums by record label]] im08732kf8vr5yna1xwsz7dwjggfv05 Hummin' Comin' at Ya 0 179447 769792 2026-10-22T20:02:07Z Jaheim Ember 76112 Created page with "{{More citations needed|date=June 2024}} {{Use mdy dates|date=May 2025}} {{Infobox album | name = Hummin' Comin' at Ya | type = Album | artist = [[Xscape (group)|Xscape]] | cover = | released = October 12, 2003 | recorded = 2002–2003 | genre = {{hlist|[[Contemporary R&B|R&B]]|[[pop music|pop]]}} | length = | label = {{hlist|[[Roc-A-Wear Records|Roc-A-Wear]]|[[Interscope Records|Interscope]]}} | producer = {..." 769792 wikitext text/x-wiki {{More citations needed|date=June 2024}} {{Use mdy dates|date=May 2025}} {{Infobox album | name = Hummin' Comin' at Ya | type = Album | artist = [[Xscape (group)|Xscape]] | cover = | released = October 12, 2003 | recorded = 2002–2003 | genre = {{hlist|[[Contemporary R&B|R&B]]|[[pop music|pop]]}} | length = | label = {{hlist|[[Roc-A-Wear Records|Roc-A-Wear]]|[[Interscope Records|Interscope]]}} | producer = {{hlist|[[Jaheim Hines]]|[[Luis Bass]]|[[Earhtone III]]}} | prev_title = [[Traces of My Lipstick]] | prev_year = 1998 | next_title = [[On the Hook (album)|On the Hook]] | next_year = 2005 | misc = {{Singles | name = Hummin' Comin' at Ya | type = studio | single1 = [[I'm So into You (song)|I'm So into You]] | single1date = August 17, 2003 | single2 = [[Weak (Xscape song)|Weak]] | single2date = December 21, 2003 | single3 = [[You're Always on My Mind (Xscape song)|You're Always on My Mind]] | single3date = January 6, 2004 | single4 = Downtown | single4date = April 11, 2004 }} }} '''''Hummin' Comin' at Ya''''' is the fourth studio album by [[United States|American]] R&B group [[Xscape (group)|Xscape]]. Released on October 12, 2003, by [[Roc-A-Wear Records]] and [[Interscope Records]]. == Track listing == ==Credits and personnel== ==Charts== ==Certifications== ==References== {{reflist}} {{Xscape}} {{Authority control}} [[Category:Xscape (group) albums]] [[Category:2003 albums]] [[Category:Roc-A-Wear Records albums]] [[Category:Interscope Records albums]] [[Category:Albums produced by Jaheim Hines]] 0va0oq34xvivuepn42agflqup00ri1j 769793 769792 2026-10-22T20:02:24Z Jaheim Ember 76112 769793 wikitext text/x-wiki {{More citations needed|date=June 2024}} {{Use mdy dates|date=May 2025}} {{Infobox album | name = Hummin' Comin' at Ya | type = Album | artist = [[Xscape (group)|Xscape]] | cover = | released = October 12, 2003 | recorded = 2002–2003 | genre = {{hlist|[[Contemporary R&B|R&B]]|[[pop music|pop]]}} | length = | label = {{hlist|[[Roc-A-Wear Records|Roc-A-Wear]]|[[Interscope Records|Interscope]]}} | producer = {{hlist|[[Jaheim Hines]]|[[Luis Bass]]|[[Earthtone III]]}} | prev_title = [[Traces of My Lipstick]] | prev_year = 1998 | next_title = [[On the Hook (album)|On the Hook]] | next_year = 2005 | misc = {{Singles | name = Hummin' Comin' at Ya | type = studio | single1 = [[I'm So into You (song)|I'm So into You]] | single1date = August 17, 2003 | single2 = [[Weak (Xscape song)|Weak]] | single2date = December 21, 2003 | single3 = [[You're Always on My Mind (Xscape song)|You're Always on My Mind]] | single3date = January 6, 2004 | single4 = Downtown | single4date = April 11, 2004 }} }} '''''Hummin' Comin' at Ya''''' is the fourth studio album by [[United States|American]] R&B group [[Xscape (group)|Xscape]]. Released on October 12, 2003, by [[Roc-A-Wear Records]] and [[Interscope Records]]. == Track listing == ==Credits and personnel== ==Charts== ==Certifications== ==References== {{reflist}} {{Xscape}} {{Authority control}} [[Category:Xscape (group) albums]] [[Category:2003 albums]] [[Category:Roc-A-Wear Records albums]] [[Category:Interscope Records albums]] [[Category:Albums produced by Jaheim Hines]] 72xpfdz02sjoxlip45wr1hevxhxp0f3 Wikipedia:AI noticeboard/AINB/Non-autoconfirmed reports 4 179449 769797 2026-10-22T20:21:07Z Chaotic Enby 58843 Created page with "trans guys matter too pls dont forget about our bros" 769797 wikitext text/x-wiki trans guys matter too pls dont forget about our bros 2cm85e48x3ouot78ovwaqp93bkw2q2r On the Hook (album) 0 179450 769798 2026-10-22T20:24:38Z Jaheim Ember 76112 Created page with "{{Use mdy dates|date=May 2025}} {{Infobox album | name = On the Hook | type = studio | artist = [[Xscape (band)|Xscape]] | cover = | released = July 11, 2005 | recorded = 2004–2005 | genre = [[Contemporary R&B|R&B]] | length = | label = {{hlist|[[Roc-A-Wear Records|Roc-A-Wear]]|[[Interscope Records|Interscope]]}} | producer = *[[Jaheim Hines]] *[[Earthtone III]] *[[Dallas Austin]] | prev_title = [[Hummin' Comin' at Ya]] | pre..." 769798 wikitext text/x-wiki {{Use mdy dates|date=May 2025}} {{Infobox album | name = On the Hook | type = studio | artist = [[Xscape (band)|Xscape]] | cover = | released = July 11, 2005 | recorded = 2004–2005 | genre = [[Contemporary R&B|R&B]] | length = | label = {{hlist|[[Roc-A-Wear Records|Roc-A-Wear]]|[[Interscope Records|Interscope]]}} | producer = *[[Jaheim Hines]] *[[Earthtone III]] *[[Dallas Austin]] | prev_title = [[Hummin' Comin' at Ya]] | prev_year = 2003 | next_title = [[Traces of Your Lipstick]] | next_year = 2008 | misc = {{Singles | name = On The Hook | type = studio | single1 = [[You're the One (Xscape song)|You're the One]] | single1date = June 6, 2005 | single2 = [[Use Your Heart (song)|Use Your Heart]] | single2date = October 3, 2005 | single3 = [[It's All About U/Anything]] | single3date = February 2, 2006 }} }} '''''On the Hook''''' is the fifth studio album by American R&B group [[Xscape (group)|Xscape]]. It was released on July 11, 2005, through [[Roc-A-Wear Records]] and [[Interscope Records]]. ==Track listing== ==Credits and personnel== ==Charts== ==Certifications== ==References== {{reflist}} {{Xscape}} {{Authority control}} [[Category:2005 albums]] [[Category:Xscape (group) albums]] [[Category:Albums produced by Jaheim Hines]] [[Category:Albums produced by Earthtone III]] 5otfx9s2sre58z09whobhkgwib0bd74 Traces of Your Lipstick 0 179451 769805 2026-10-22T20:39:23Z Jaheim Ember 76112 Created page with "{{Use mdy dates|date=May 2025}} {{Infobox album | name = Traces of Your Lipstick | type = studio | artist = [[Xscape (group)|Xscape]] | cover = | released = May 12, 2008 | recorded = 2007–2008 | genre = [[Contemporary R&B|R&B]] | length = | label = {{hlist|[[Roc-A-Wear Records|Roc-A-Wear]]|[[Interscope Records|Interscope]]}} | producer = *[[Rodney Jerkins]] *[[Jaheim Hines]] *[[Raphael Saadiq]] *[[Fred Jerkins III]] *Babyfa..." 769805 wikitext text/x-wiki {{Use mdy dates|date=May 2025}} {{Infobox album | name = Traces of Your Lipstick | type = studio | artist = [[Xscape (group)|Xscape]] | cover = | released = May 12, 2008 | recorded = 2007–2008 | genre = [[Contemporary R&B|R&B]] | length = | label = {{hlist|[[Roc-A-Wear Records|Roc-A-Wear]]|[[Interscope Records|Interscope]]}} | producer = *[[Rodney Jerkins]] *[[Jaheim Hines]] *[[Raphael Saadiq]] *[[Fred Jerkins III]] *[[Babyface (musician)|Babyface]] *[[Tamika Scott]] *[[Dallas Austin]] *Soulpower Productions *[[Timbaland]] | prev_title = [[On the Hook (album)|On the Hook]] | prev_year = 2005 | next_title = [[Here for It]] | next_year = 2018 | misc = {{Singles | name = Traces of Your Lipstick | type = studio | single1 = [[Believe Again (Xscape song)|Believe Again]] | single1date = February 14, 2008 | single2 = [[Good Luck Charm (Xscape song)|Good Luck Charm]] | single2date = July 7, 2008 | single3 = The Color of Love | single3date = September 29, 2008 }} }} '''''Traces of Your Lipstick''''' is the sixth studio album by American R&B group [[Xscape (group)|Xscape]]. The album was released on May 12, 2008, through [[Roc-A-Wear Records]] and [[Columbia Records]]. ==Background and release== ==Promotion== ==Track listing== ==Credits and personnel== ==Charts== ==Certifications== ==References== {{Reflist}} {{Xscape}} {{Authority control}} {{DEFAULTSORT:Traces Of Your Lipstick}} [[Category:2008 albums]] [[Category:Albums produced by Jaheim Hines]] [[Category:Albums produced by Rodney Jerkins]] [[Category:Xscape (group) albums]] eyfarnhnlsg46lw3nxrtxxgcodajlrx Wikipedia:Sandbox/MoveIt moved 2026-10-23T11-33-25-828Z 4 179452 769833 2026-10-23T11:33:26Z Closed Limelike Curves 60396 MoveIt live rename test: creating the page to be renamed 769833 wikitext text/x-wiki Throwaway page for the Move It live rename test (2026-10-23T11-33-25-828Z). Safe to delete. 8egj0ps3z39nbwj27zjwqrvzuhehbzo 769834 769833 2026-10-23T11:33:27Z Closed Limelike Curves 60396 Closed Limelike Curves moved page [[Wikipedia:Sandbox/MoveIt move 2026-10-23T11-33-25-828Z]] to [[Wikipedia:Sandbox/MoveIt moved 2026-10-23T11-33-25-828Z]]: Move It live rename test (via Move It browser extension) 769833 wikitext text/x-wiki Throwaway page for the Move It live rename test (2026-10-23T11-33-25-828Z). Safe to delete. 8egj0ps3z39nbwj27zjwqrvzuhehbzo 769837 769834 2026-10-23T11:33:29Z Closed Limelike Curves 60396 MoveIt live rename test teardown 769837 wikitext text/x-wiki phoiac9h4m842xq45sp7s6u21eteeq1 Wikipedia:Sandbox/MoveIt move 2026-10-23T11-33-25-828Z 4 179453 769835 2026-10-23T11:33:28Z Closed Limelike Curves 60396 Closed Limelike Curves moved page [[Wikipedia:Sandbox/MoveIt move 2026-10-23T11-33-25-828Z]] to [[Wikipedia:Sandbox/MoveIt moved 2026-10-23T11-33-25-828Z]]: Move It live rename test (via Move It browser extension) 769835 wikitext text/x-wiki #REDIRECT [[Wikipedia:Sandbox/MoveIt moved 2026-10-23T11-33-25-828Z]] {{Redirect category shell| {{R from move}} }} nj9njv8a027aklq9f2bpxl5lrpk6323 769836 769835 2026-10-23T11:33:29Z Closed Limelike Curves 60396 MoveIt live rename test teardown 769836 wikitext text/x-wiki phoiac9h4m842xq45sp7s6u21eteeq1