diff --git a/bower.json b/bower.json index df4e7af..5282e90 100644 --- a/bower.json +++ b/bower.json @@ -19,11 +19,11 @@ ], "dependencies": { "Atem-Pen-Case": "graphicore/Atem-Pen-Case", - "opentype.js": "^0.7.3", - "requirejs": "~2.3.2", - "requirejs-text": "~2.0.15" - }, - "resolutions": { - "opentype.js": "^0.7.3" + "opentype.js": "^1.1.0", + "requirejs": "^2.3.6", + "text": "requirejs-text#^2.0.16", + "marked": "^0.8.2", + "DOMPurify": "^2.0.8", + "mustache.js": "^4.0.1" } } diff --git a/content/font_testing/includes/latin-02/briem.htmlpart b/content/font_testing/includes/latin-02/briem.htmlpart new file mode 100644 index 0000000..c088efb --- /dev/null +++ b/content/font_testing/includes/latin-02/briem.htmlpart @@ -0,0 +1,47 @@ +
+ +

32px

+

+ Ay Aw Av A' AY AW AV AT F. F, FA Ly L' LY LW LV LT P. P, PA Ry RY RW RV RT Ty Tw Tu T; Ts Tr T. To Ti T- Te T, T: Tc Ta TA Vy Vu V; Vr V. Vo Vi V- Ve V, V: Va VA Wy Wu W; Wr W. Wo Wi W- We W, W: Wa WA Yv Yu Y; Yq Y. Yp Yo Yi Y- Ye Y, Y: Ya YA
+ f' ff `` 't 's '' rz ry rx rw rv ru rt rr r' rq r. ro rn rm r- rh rg rf re rd r, rc v. v, w. w, y. y, n. r. v. w. y. n-n o-o
+
+ nnannbnncnndnnenn
+ nnfnngnnhnninnjnn
+ nnknnlnnmnnonnpnn
+ nnqnnrnnsnntnnunn
+ nnvnnwnnxnnynnznn
+
+ ooaooboocoodooeoo
+ oofoogoohooioojoo
+ ookooloomoonoopoo
+ ooqooroosootoouoo
+ oovoowooxooyoozoo
+
+ nnAnnBnnCnn
+ nnDnnEnnFnnGnnHnn
+ nnInnJnnKnnLnnMnn
+ nnNnnOnnPnnQnnRnn
+ nnSnnTnnUnnVnnWnn
+ nnXnnYnnZnn
+
+ ooAooBooCoo
+ ooDooEooFooGooHoo
+ ooIooJooKooLooMoo
+ ooNooOooPooQooRoo
+ ooSooTooUooVooWoo
+ ooXooYooZoo
+
+ H H A H H T H H V H H W H H Y H H
+ O O A O O T O O V O O W O O Y O O
+
+ HAHBHCHDHEHFH
+ HGHIHJHKHLHMHNH
+ HNHOHPHQHRHSHTH
+ HUHVHWHXHYHZH
+
+ OAOBOCODOEOFO
+ OGOHOIOJOKOLOMO
+ ONOPOQOROSOTO
+ OUOVOWOXOYOZO

+ +
\ No newline at end of file diff --git a/content/font_testing/includes/latin-02/kern-king.htmlpart b/content/font_testing/includes/latin-02/kern-king.htmlpart new file mode 100644 index 0000000..104fdd8 --- /dev/null +++ b/content/font_testing/includes/latin-02/kern-king.htmlpart @@ -0,0 +1,18 @@ +
+ +

Source: Leslie Cabarga's Kern King http://logofontandlettering.com/kernking.html

+

 

+ +

Part 1: All Lowercase - 32px

+

lynx tuft frogs, dolphins abduct by proxy the ever awkward klutz, dud, dummkopf, jinx snubnose filmgoer, orphan sgt. renfruw grudgek reyfus, md. sikh psych if halt tympany jewelry sri heh! twyer vs jojo pneu fylfot alcaaba son of nonplussed halfbreed bubbly playboy guggenheim daddy coccyx sgraffito effect, vacuum dirndle impossible attempt to disvalue, muzzle the afghan czech czar and exninja, bob bixby dvorak wood dhurrie savvy, dizzy eye aeon circumcision uvula scrungy picnic luxurious special type carbohydrate ovoid adzuki kumquat bomb? afterglows gold girl pygmy gnome lb. ankhs acme aggroupment akmed brouhha tv wt. ujjain ms. oz abacus mnemonics bhikku khaki bwana aorta embolism vivid owls often kvetch otherwise, wysiwyg densfort wright you’ve absorbed rhythm, put obstacle kyaks krieg kern wurst subject enmity equity coquet quorum pique tzetse hepzibah sulfhydryl briefcase ajax ehler kafka fjord elfship halfdressed jugful eggcup hummingbirds swingdevil bagpipe legwork reproachful hunchback archknave baghdad wejh rijswijk rajbansi rajput ajdir okay weekday obfuscate subpoena liebknecht marcgravia ecbolic arcticward dickcissel pincpinc boldface maidkin adjective adcraft adman dwarfness applejack darkbrown kiln palzy always farmland flimflam unbossy nonlineal stepbrother lapdog stopgap sx countdown basketball beaujolais vb. flowchart aztec lazy bozo syrup tarzan annoying dyke yucky hawg gagzhukz cuzco squire when hiho mayhem nietzsche szasz gumdrop milk emplotment ambidextrously lacquer byway ecclesiastes stubchen hobgoblins crabmill aqua hawaii blvd. subquality byzantine empire debt obvious cervantes jekabzeel anecdote flicflac mechanicville bedbug couldn’t i’ve it’s they’ll they’d dpt. headquarter burkhardt xerxes atkins govt. ebenezer lg. lhama amtrak amway fixity axmen quumbabda upjohn hrumpf

+

 

+ +

Part 1: All Uppercase - 32px

+

LYNX TUFT FROGS, DOLPHINS ABDUCT BY PROXY THE EVER AWKWARD KLUTZ, DUD, DUMMKOPF, JINX SNUBNOSE FILMGOER, ORPHAN SGT. RENFRUW GRUDGEK REYFUS, MD. SIKH PSYCH IF HALT TYMPANY JEWELRY SRI HEH! TWYER VS JOJO PNEU FYLFOT ALCAABA SON OF NONPLUSSED HALFBREED BUBBLY PLAYBOY GUGGENHEIM DADDY COCCYX SGRAFFITO EFFECT, VACUUM DIRNDLE IMPOSSIBLE ATTEMPT TO DISVALUE, MUZZLE THE AFGHAN CZECH CZAR AND EXNINJA, BOB BIXBY DVORAK WOOD DHURRIE SAVVY, DIZZY EYE AEON CIRCUMCISION UVULA SCRUNGY PICNIC LUXURIOUS SPECIAL TYPE CARBOHYDRATE OVOID ADZUKI KUMQUAT BOMB? AFTERGLOWS GOLD GIRL PYGMY GNOME LB. ANKHS ACME AGGROUPMENT AKMED BROUHHA TV WT. UJJAIN MS. OZ ABACUS MNEMONICS BHIKKU KHAKI BWANA AORTA EMBOLISM VIVID OWLS OFTEN KVETCH OTHERWISE, WYSIWYG DENSFORT WRIGHT YOU’VE ABSORBED RHYTHM, PUT OBSTACLE KYAKS KRIEG KERN WURST SUBJECT ENMITY EQUITY COQUET QUORUM PIQUE TZETSE HEPZIBAH SULFHYDRYL BRIEFCASE AJAX EHLER KAFKA FJORD ELFSHIP HALFDRESSED JUGFUL EGGCUP HUMMINGBIRDS SWINGDEVIL BAGPIPE LEGWORK REPROACHFUL HUNCHBACK ARCHKNAVE BAGHDAD WEJH RIJSWIJK RAJBANSI RAJPUT AJDIR OKAY WEEKDAY OBFUSCATE SUBPOENA LIEBKNECHT MARCGRAVIA ECBOLIC ARCTICWARD DICKCISSEL PINCPINC BOLDFACE MAIDKIN ADJECTIVE ADCRAFT ADMAN DWARFNESS APPLEJACK DARKBROWN KILN PALZY ALWAYS FARMLAND FLIMFLAM UNBOSSY NONLINEAL STEPBROTHER LAPDOG STOPGAP SX COUNTDOWN BASKETBALL BEAUJOLAIS VB. FLOWCHART AZTEC LAZY BOZO SYRUP TARZAN ANNOYING DYKE YUCKY HAWG GAGZHUKZ CUZCO SQUIRE WHEN HIHO MAYHEM NIETZSCHE SZASZ GUMDROP MILK EMPLOTMENT AMBIDEXTROUSLY LACQUER BYWAY ECCLESIASTES STUBCHEN HOBGOBLINS CRABMILL AQUA HAWAII BLVD. SUBQUALITY BYZANTINE EMPIRE DEBT OBVIOUS CERVANTES JEKABZEEL ANECDOTE FLICFLAC MECHANICVILLE BEDBUG COULDN’T I’VE IT’S THEY’LL THEY’D DPT. HEADQUARTER BURKHARDT XERXES ATKINS GOVT. EBENEZER LG. LHAMA AMTRAK AMWAY FIXITY AXMEN QUUMBABDA UPJOHN HRUMPF

+

 

+ +

Part 2: Most Common Initial Caps - 32px

+

Aaron Abraham Adam Aeneas Agfa Ahoy Aileen Akbar Alanon Americanism Anglican Aorta April Fool’s Day Aqua Lung (Tm.) Arabic Ash Wednesday Authorized Version Ave Maria Away Axel Ay Aztec Bhutan Bill Bjorn Bk Btu. Bvart Bzonga California Cb Cd Cervantes Chicago Clute City, Tx. Cmdr. Cnossus Coco Cracker State, Georgia Cs Ct. Cwacker Cyrano David Debra Dharma Diane Djakarta Dm Dnepr Doris Dudley Dwayne Dylan Dzerzhinsk Eames Ectomorph Eden Eerie Effingham, Il. Egypt Eiffel Tower Eject Ekland Elmore Entreaty Eolian Epstein Equine Erasmus Eskimo Ethiopia Europe Eva Ewan Exodus Jan van Eyck Ezra Fabian February Fhara Fifi Fjord Florida Fm France Fs Ft. Fury Fyn Gabriel Gc Gdynia Gehrig Ghana Gilligan Karl Gjellerup Gk. Glen Gm Gnosis Gp.E. Gregory Gs Gt. Br. Guinevere Gwathmey Gypsy Gzags Hebrew Hf Hg Hileah Horace Hrdlicka Hsia Hts. Hubert Hwang Hai Hyacinth Hz. Iaccoca Ibsen Iceland Idaho If Iggy Ihre Ijit Ike Iliad Immediate Innocent Ione Ipswitch Iquarus Ireland Island It Iud Ivert Iwerks Ixnay Iy Jasper Jenks Jherry Jill Jm Jn Jorge Jr. Julie Kerry Kharma Kiki Klear Koko Kruse Kusack Kylie Laboe Lb. Leslie Lhihane Llama Lorrie Lt. Lucy Lyle Madeira Mechanic Mg. Minnie Morrie Mr. Ms. Mt. Music My Nanny Nellie Nillie Novocane Null Nyack Oak Oblique Occarina Odd Oedipus Off Ogmane Ohio Oil Oj Oklahoma Olio Omni Only Oops Opera Oqu Order Ostra Ottmar Out Ovum Ow Ox Oyster Oz Parade Pd. Pepe Pfister Pg. Phil Pippi Pj Please Pneumonia Porridge Price Psalm Pt. Purple Pv Pw Pyre Qt. Quincy Radio Rd. Red Rhea Right Rj Roche Rr Rs Rt. Rural Rwanda Ryder Sacrifice Series Sgraffito Shirt Sister Skeet Slow Smore Snoop Soon Special Squire Sr St. Suzy Svelte Swiss Sy Szach Td Teach There Title Total Trust Tsena Tulip Twice Tyler Tzean Ua Udder Ue Uf Ugh Uh Ui Uk Ul Um Unkempt Uo Up Uq Ursula Use Utmost Uvula Uw Uxurious Uzßai Valerie Velour Vh Vicky Volvo Vs Water Were Where With World Wt. Wulk Wyler Xavier Xerox Xi Xylophone Yaboe Year Yipes Yo Ypsilant Ys Yu Zabar’s Zero Zhane Zizi Zorro Zu Zy Don’t I’ll I’m I’se

+

 

+ +
\ No newline at end of file diff --git a/content/font_testing/includes/latin-02/kern-minimal.htmlpart b/content/font_testing/includes/latin-02/kern-minimal.htmlpart new file mode 100644 index 0000000..b3062bd --- /dev/null +++ b/content/font_testing/includes/latin-02/kern-minimal.htmlpart @@ -0,0 +1,103 @@ +
+ +

Impallari's Minimal Kerning Pairs Checklist

+

 

+ +

Cap to Cap

+

+ HHATAHH HHTÆHH
+ HHAUAHH HHUÆHH
+ HHAVAHH HHVÆHH
+ HHAWAHH HHWÆHH
+ HHAYAHH HHYÆHH
+ HHAOAHH HHAQAHH HHACHH HHAGHH HHDAHH
+ HHOÆHH HHDÆHH HHQÆHH
+ HHOTOHH HHQTQHH HHDTHH HHTCHH HHTGHH
+ HHOVOHH HHQVQHH HHDVHH HHVCHH HHVGHH
+ HHOWOHH HHQWQHH HHDWHH HHWCHH HHWGHH
+ HHOXOHH HHQXQHH HHDXHH HHXCHH HHXGHH
+ HHOYOHH HHQYQHH HHDYHH HHYCHH HHYGHH
+ HHKOHH HHKCHH HHKGHH HHKQHH
+ HHLOHH HHLCHH HHLGHH HHLQHH
+ HHEOHH HHECHH HHEGHH HHEQHH
+ HHFOHH HHFCHH HHFGHH HHFQHH
+ HHFAHH HHFÆHH
+ HHPAHH HHPÆHH
+ HHSYHH HHYSHH
+ HHBTHH HHLTHH HHRTHH
+ HHBVHH HHLVHH HHPVHH HHRVHH HHGVHH
+ HHBWHH HHLWHH HHPWHH HHRWHH HHGWHH
+ HHBXHH HHLXHH HHPXHH HHRXHH HHGXHH
+ HHBYHH HHLYHH HHPYHH HHRYHH HHGYHH
+ HHFJHH HHPJHH HHTJHH HHVJHH HHWJHH HHYJHH
+ HHLUHH HHRUHH
+ HHAAHH HHLAHH HHRAHH HHKAHH
+

+

 

+ +

Cap to Lower

+

+ Fannon Kannon Pannon Tannon Vannon Wannon Yannon
+ Fcnnon Kcnnon Pcnnon Tcnnon Vcnnon Wcnnon Xcnnon Ycnnon
+ Fdnnon Kdnnon Pdnnon Tdnnon Vdnnon Wdnnon Xdnnon Ydnnon
+ Fennon Kennon Pennon Tennon Vennon Wennon Xennon Yennon
+ Fqnnon Kqnnon Pqnnon Tqnnon Vqnnon Wqnnon Xqnnon Yqnnon
+ Fonnon Konnon Ponnon Tonnon Vonnon Wonnon Xonnon Yonnon
+ Fgnnon Kgnnon Pgnnon Tgnnon Vgnnon Wgnnon Xgnnon Ygnnon
+ Vinnon Winnon Yinnon
+ Tmnnon Vmnnon Wmnnon Ymnnon
+ Tnnnon Vnnnon Wnnnon Ynnnon
+ Tpnnon Vpnnon Wpnnon Ypnnon
+ Trnnon Vrnnon Wrnnon Yrnnon
+ Tsnnon Vsnnon Wsnnon Ysnnon
+ Atnnon Ytnnon
+ Funnon Kunnon Tunnon Vunnon Wunnon Yunnon Xunnon
+ Avnnon Kvnnon Lvnnon Tvnnon Vvnnon Yvnnon Xvnnon
+ Awnnon Kwnnon Lwnnon Twnnon Vwnnon Ywnnon Xwnnon
+ Txnnon Yxnnon
+ Aynnon Kynnon Lynnon Tynnon Vynnon Wynnon Yynnon Xynnon
+ Tznnon Yznnon

+

 

+ +

Lower to Lower

+

+ nonavnon nonvanon nonawnon nonwanon
+ nonovonon noncvcnon nonevenon nonbvdnon nonpvqnon
+ nonowonon noncwcnon nonewenon nonbwdnon nonpwqnon
+ nonoxonon noncxcnon nonexenon nonbxdnon nonpxqnon
+ nonoyonon noncycnon noneyenon nonbydnon nonpyqnon
+ nonkonon nonkcnon nonkenon nonkdnon nonkqnon
+ nonranon nonronon nonrcnon nonrenon nonrdnon nonrqnon
+ nonofonon noncfcnon nonefenon nonbfdnon nonpfqnon
+ nonotonon nonctcnon nonetenon nonbtdnon nonptqnon

+

 

+ +

Caps and punctuation

+

+ HH‘AHH HHA’HH HH’AHH HH‘OHH HHO’HH HH’OHH HHL’HH
+ HH“AHH HHA”HH HH”AHH HH“OHH HHO”HH HH”OHH HHL”HH
+ HH'A'HH HH'O'HH HHL'HH HH"A"HH HH"O"HH HHL"HH
+ HH*A*HH HH*O*HH HHL*HH
+ HH.O.HH HH.T.HH HH.U.HH HH.V.HH HH.W.HH HH.Y.HH
+ HHD.HH HHF.HH HHP.HH
+ HH,O,HH HH,T,HH HH,U,HH HH,V,HH HH,W,HH HH,Y,HH
+ HHD,HH HHF,HH HHP,HH
+ HHK-HH HHL-HH
+ HH-T-HH HH-V-HH HH-W-HH HH-X-HH HH-Y-HH HH-Z-HH
+ HHT:HH HHV:HH HHW:HH HHY:HH
+ HHT;HH HHV;HH HHW;HH HHY;HH
+ HH¿JHH HH¡JHH

+

 

+ +

Lower and punctuation

+

+ nn.f.nn nn.o.nn nn.v.nn nn.w.nn nn.y.nn nnr.nn
+ nn,f,nn nn,o,nn nn,v,nn nn,w,nn nn,y,nn nnr,nn
+ nonf*non nonf?non non(f)non non[f]non non{f}non
+ nonf'non nonf"non nonf’non nonf”non nonf‘non nonf“non
+ non¿jnon non(j)non non[j]non non{j}non
+ nonk-non nonr-non non-x-non
+ non’snon

+

 

+ +
\ No newline at end of file diff --git a/content/font_testing/includes/latin-02/kern-words.htmlpart b/content/font_testing/includes/latin-02/kern-words.htmlpart new file mode 100644 index 0000000..4b51797 --- /dev/null +++ b/content/font_testing/includes/latin-02/kern-words.htmlpart @@ -0,0 +1,60 @@ +
+

32px Sentence Case

+

Abbygail Ability Abrupt Absolute Academy Accept Acquaint Action Adapt Adjunct Admirers Adverb Aegean Aeroport Aesthete Affable After Again Aggregate Agriculture Aha Alliteration Alpine Aluminum Always American Animal Anyway Aorta Aplomb Appear Apron Aqua Ardennes Arrange Asop Assimilate Assume Attitude Auction Average Avor Awesome Awful Awkward Axis Azureße

 

+

Backfire Background Ball Bangkok Banquet Baptism Barge Bashful Basque Bawl Bazaar Bel Bedpost Beefeater Beginning Behind Bellhop Bezel Bigtown Bismarck Blackjack Blacktop Blazer Blitz Bloom Blow Bobcat Bookcase Boxwood Bozo Brawn Brunch Buggy Bulge Bummer Buys Bygone Byte Byzantine

 

+

Calculate Camp Cantor Cash Celebration Certified Chamfer Child Chimney Church Circumflex Circumvent Clervaux Clever Cobweb Cockpit Cod Coffee Comb Community Company Cook Cop Coral Cotton Could Cover Crest Croquet Crowd Cupboard Cupcake Cutback

 

+

Dab Damage Damsel Daring Dass Dauntless Dawg Declared Deliver Did Dimly Dinner Dirty Does Donut Doppler Dose Dragon Drink Drive Dynamo

 

+

Each Earthquake Ebb Eccentric Economy Ecstasy Edelweiss Efficient Effort Egger Eggs Egypt Eject Elbows Elevate Eliminate Eminent Enterprise Eons Equestrian Equip Erschrift Erase Essence Estrange Etiquette Europe Everyday Everything Evolve Exact Excel Exchange Exhausting Expectation Extra Eyeball

 

+

Fall Fashion Fasting Feet Fence Fetch Fight Fishpond Flower Fluffy Fluid Fluss Font Forget Franklin Fridge Fun

 

+

Game Gel Get Girder Golly Gone Gong Goon Great Grope Gurge Gymnast

 

+

Halfway Halt Happy Harm Harness Healthier Helpful Hobo Homology Honeymoon Honor Hornet Hotplate How Humanity Humility Hundred Hybrid Hygienic

 

+

Icon Idiot Ignore Illumination Important Infinite Intrepid Invincible Irritate Iterate

 

+

Jar Jazzy Jelly Joint Joke Judgment Jumped Justice Juvenile

 

+

Kellogs Kind King Knight Knowledge Kumquat Kwikset

 

+

Lab Lesson Lightning Little Logjam Loner Long Lung

 

+

Manufacture Map Mash Master Mathematics May Medieval Member Men Mercy Metrics Minimum Misframe Mist Mother Mr. Ms Myself

 

+

Nanny Nasty Neither Nell Nerve Newmarket Nile Non Nothing Noxious

 

+

Oat Obfuscate Oblong Obstruct Obvious Octagon Oddball Oddity Offbeat Offensive Offer Offhand Offprint Oily Olympic Ominous Only Onyx Opportunity Optical Orange Ourselves Out Owl Oxbow Oxymoron

 

+

Paper Parcel Parks Parse Particularly Paths Pearl Pencil Pepper Perfect Pest Phase Philosophy Physical Pillow Plural Pod Popper Poppy Popular Portal Potter Preprint Pressure Price Prize Pro Puppet Puppy Pushcart

 

+

Queen Question Qwertzuiop

 

+

Receive Record Red Reek Referee Rest Retro Ripped Risk Roses Rower Runny

 

+

Said Sam Sample Sand Sap Say School Shame Shine Shop Sick Significant Silken Silly Sister Sitting Skate Skill Slab Slave Slip Slop Slot Slow Smell Smoke Snoop Snow Soap Sock Soggy Soho Sorrow Soup South Spoke Spruce Square Squid Star Stickman Stiffs Stop Street Strofe Subhead Subject Submit Subplot Subs Subtle Subtype Success Sue Suffer Sultry Sunny Superb Surprise Sword System

 

+

Ter Tambourine Tangerine Task Tatter Taxman Temptation Tenaru Tennis Terminal Terry Tests Theater Themselves Theology They Think Those Thoughtless Thud Thug Thwack Tippy Tipsy Tomorrow Toronto Total Trac Trial Troy Truck Truk Tub Tuna Tungsten Typografie Tussie Twist Type Typhoon

 

+

Ugly Uh Umbrella Undefined Underwear Upbeat Upper Uptown Usage Utter

 

+

Valley Valve Vampire Vat Vegetable Very Vile Vindicator Vodka Volga Volume Volva Vrooooom Vulcan Vulgar

 

+

Wack Wacombiere Waft Wallow Werme Warmth Warps Wasp Wavy Web Wedding Welcome Wheeler When Whine Wildcat Winter Woman Wonder Woodlark World Worry Wreck Wring Wunder Warmer

 

+

Xray

 

+

Yankee Year Yellow Yippee Yours

 

+

Zealous Zero Zigzag Zombie Zurich Zygote

+ +

 

+ +

32px All Caps

+

ABBYGAIL ABILITY ABRUPT ABSOLUTE ACADEMY ACCEPT ACQUAINT ACTION ADAPT ADJUNCT ADMIRERS ADVERB AEGEAN AEROPORT AESTHETE AFFABLE AFTER AGAIN AGGREGATE AGRICULTURE AHA ALLITERATION ALPINE ALUMINUM ALWAYS AMERICAN ANIMAL ANYWAY AORTA APLOMB APPEAR APRON AQUA ARDENNES ARRANGE ASOP ASSIMILATE ASSUME ATTITUDE AUCTION AVERAGE AVOR AWESOME AWFUL AWKWARD AXIS AZUREßE

 

+

BACKFIRE BACKGROUND BALL BANGKOK BANQUET BAPTISM BARGE BASHFUL BASQUE BAWL BAZAAR BEL BEDPOST BEEFEATER BEGINNING BEHIND BELLHOP BEZEL BIGTOWN BISMARCK BLACKJACK BLACKTOP BLAZER BLITZ BLOOM BLOW BOBCAT BOOKCASE BOXWOOD BOZO BRAWN BRUNCH BUGGY BULGE BUMMER BUYS BYGONE BYTE BYZANTINE

 

+

CALCULATE CAMP CANTOR CASH CELEBRATION CERTIFIED CHAMFER CHILD CHIMNEY CHURCH CIRCUMFLEX CIRCUMVENT CLERVAUX CLEVER COBWEB COCKPIT COD COFFEE COMB COMMUNITY COMPANY COOK COP CORAL COTTON COULD COVER CREST CROQUET CROWD CUPBOARD CUPCAKE CUTBACK

 

+

DAB DAMAGE DAMSEL DARING DASS DAUNTLESS DAWG DECLARED DELIVER DID DIMLY DINNER DIRTY DOES DONUT DOPPLER DOSE DRAGON DRINK DRIVE DYNAMO

 

+

EACH EARTHQUAKE EBB ECCENTRIC ECONOMY ECSTASY EDELWEISS EFFICIENT EFFORT EGGER EGGS EGYPT EJECT ELBOWS ELEVATE ELIMINATE EMINENT ENTERPRISE EONS EQUESTRIAN EQUIP ERSCHRIFT ERASE ESSENCE ESTRANGE ETIQUETTE EUROPE EVERYDAY EVERYTHING EVOLVE EXACT EXCEL EXCHANGE EXHAUSTING EXPECTATION EXTRA EYEBALL

 

+

FALL FASHION FASTING FEET FENCE FETCH FIGHT FISHPOND FLOWER FLUFFY FLUID FLUSS FONT FORGET FRANKLIN FRIDGE FUN

 

+

GAME GEL GET GIRDER GOLLY GONE GONG GOON GREAT GROPE GURGE GYMNAST

 

+

HALFWAY HALT HAPPY HARM HARNESS HEALTHIER HELPFUL HOBO HOMOLOGY HONEYMOON HONOR HORNET HOTPLATE HOW HUMANITY HUMILITY HUNDRED HYBRID HYGIENIC

 

+

ICON IDIOT IGNORE ILLUMINATION IMPORTANT INFINITE INTREPID INVINCIBLE IRRITATE ITERATE

 

+

JAR JAZZY JELLY JOINT JOKE JUDGMENT JUMPED JUSTICE JUVENILE

 

+

KELLOGS KIND KING KNIGHT KNOWLEDGE KUMQUAT KWIKSET

 

+

LAB LESSON LIGHTNING LITTLE LOGJAM LONER LONG LUNG

 

+

MANUFACTURE MAP MASH MASTER MATHEMATICS MAY MEDIEVAL MEMBER MEN MERCY METRICS MINIMUM MISFRAME MIST MOTHER MR. MS MYSELF

 

+

NANNY NASTY NEITHER NELL NERVE NEWMARKET NILE NON NOTHING NOXIOUS

 

+

OAT OBFUSCATE OBLONG OBSTRUCT OBVIOUS OCTAGON ODDBALL ODDITY OFFBEAT OFFENSIVE OFFER OFFHAND OFFPRINT OILY OLYMPIC OMINOUS ONLY ONYX OPPORTUNITY OPTICAL ORANGE OURSELVES OUT OWL OXBOW OXYMORON

 

+

PAPER PARCEL PARKS PARSE PARTICULARLY PATHS PEARL PENCIL PEPPER PERFECT PEST PHASE PHILOSOPHY PHYSICAL PILLOW PLURAL POD POPPER POPPY POPULAR PORTAL POTTER PREPRINT PRESSURE PRICE PRIZE PRO PUPPET PUPPY PUSHCART

 

+

QUEEN QUESTION QWERTZUIOP

 

+

RECEIVE RECORD RED REEK REFEREE REST RETRO RIPPED RISK ROSES ROWER RUNNY

 

+

SAID SAM SAMPLE SAND SAP SAY SCHOOL SHAME SHINE SHOP SICK SIGNIFICANT SILKEN SILLY SISTER SITTING SKATE SKILL SLAB SLAVE SLIP SLOP SLOT SLOW SMELL SMOKE SNOOP SNOW SOAP SOCK SOGGY SOHO SORROW SOUP SOUTH SPOKE SPRUCE SQUARE SQUID STAR STICKMAN STIFFS STOP STREET STROFE SUBHEAD SUBJECT SUBMIT SUBPLOT SUBS SUBTLE SUBTYPE SUCCESS SUE SUFFER SULTRY SUNNY SUPERB SURPRISE SWORD SYSTEM

 

+

TER TAMBOURINE TANGERINE TASK TATTER TAXMAN TEMPTATION TENARU TENNIS TERMINAL TERRY TESTS THEATER THEMSELVES THEOLOGY THEY THINK THOSE THOUGHTLESS THUD THUG THWACK TIPPY TIPSY TOMORROW TORONTO TOTAL TRAC TRIAL TROY TRUCK TRUK TUB TUNA TUNGSTEN TYPOGRAFIE TUSSIE TWIST TYPE TYPHOON

 

+

UGLY UH UMBRELLA UNDEFINED UNDERWEAR UPBEAT UPPER UPTOWN USAGE UTTER

 

+

VALLEY VALVE VAMPIRE VAT VEGETABLE VERY VILE VINDICATOR VODKA VOLGA VOLUME VOLVA VROOOOOM VULCAN VULGAR

 

+

WACK WACOMBIERE WAFT WALLOW WERME WARMTH WARPS WASP WAVY WEB WEDDING WELCOME WHEELER WHEN WHINE WILDCAT WINTER WOMAN WONDER WOODLARK WORLD WORRY WRECK WRING WUNDER WARMER

 

+

XRAY

 

+

YANKEE YEAR YELLOW YIPPEE YOURS

 

+

ZEALOUS ZERO ZIGZAG ZOMBIE ZURICH ZYGOTE

+ +
\ No newline at end of file diff --git a/content/font_testing/includes/latin-02/ngrams.htmlpart b/content/font_testing/includes/latin-02/ngrams.htmlpart new file mode 100644 index 0000000..5ffceae --- /dev/null +++ b/content/font_testing/includes/latin-02/ngrams.htmlpart @@ -0,0 +1,334 @@ +
+ +

32px Most common letter sequences http://norvig.com/mayzner.html

+ + + + + + + + + + +
+

e
+ t
+ a
+ o
+ i
+ n
+ s
+ r
+ h
+ l
+ d
+ c
+ u
+ m
+ f
+ p
+ g
+ w
+ y
+ b
+ v
+ k
+ x
+ j
+ q
+ z

+
+

th
+ he
+ in
+ er
+ an
+ re
+ on
+ at
+ en
+ nd
+ ti
+ es
+ or
+ te
+ of
+ ed
+ is
+ it
+ al
+ ar
+ st
+ to
+ nt
+ ng
+ se
+ ha
+ as
+ ou
+ io
+ le
+ ve
+ co
+ me
+ de
+ hi
+ ri
+ ro
+ ic
+ ne
+ ea
+ ra
+ ce
+ li
+ ch
+ ll
+ be
+ ma
+ si
+ om
+ ur

+
+

the
+ and
+ ing
+ ion
+ tio
+ ent
+ ati
+ for
+ her
+ ter
+ hat
+ tha
+ ere
+ ate
+ his
+ con
+ res
+ ver
+ all
+ ons
+ nce
+ men
+ ith
+ ted
+ ers
+ pro
+ thi
+ wit
+ are
+ ess
+ not
+ ive
+ was
+ ect
+ rea
+ com
+ eve
+ per
+ int
+ est
+ sta
+ cti
+ ica
+ ist
+ ear
+ ain
+ one
+ our
+ iti
+ rat

+
+

tion
+ atio
+ that
+ ther
+ with
+ ment
+ ions
+ this
+ here
+ from
+ ould
+ ting
+ hich
+ whic
+ ctio
+ ence
+ have
+ othe
+ ight
+ sion
+ ever
+ ical
+ they
+ inte
+ ough
+ ance
+ were
+ tive
+ over
+ ding
+ pres
+ nter
+ comp
+ able
+ heir
+ thei
+ ally
+ ated
+ ring
+ ture
+ cont
+ ents
+ cons
+ rati
+ thin
+ part
+ form
+ ning
+ ecti
+ some

+
+

ation
+ tions
+ which
+ ction
+ other
+ their
+ there
+ ition
+ ement
+ inter
+ ional
+ ratio
+ would
+ tiona
+ these
+ state
+ natio
+ thing
+ under
+ ssion
+ ectio
+ catio
+ latio
+ about
+ count
+ ments
+ rougt
+ ative
+ prese
+ feren
+ hough
+ ution
+ roduc
+ resen
+ thoug
+ press
+ first
+ after
+ cause
+ where
+ tatio
+ could
+ efore
+ contr
+ hould
+ shoul
+ tical
+ gener
+ esent
+ great

+
+

ations
+ ration
+ tional
+ nation
+ ection
+ cation
+ lation
+ though
+ presen
+ tation
+ should
+ resent
+ genera
+ dition
+ ationa
+ produc
+ throug
+ hrough
+ etween
+ betwee
+ differ
+ icatio
+ people
+ iffere
+ fferen
+ struct
+ action
+ person
+ eneral
+ system
+ relati
+ ctions
+ ecause
+ becaus
+ before
+ ession
+ develo
+ evelop
+ uction
+ change
+ follow
+ positi
+ govern
+ sition
+ merica
+ direct
+ bility
+ effect
+ americ
+ public

+
+ +

32px Most common 20 letter words

+ + + + + + + +
+

electroencephalographic
+ polytetrafluoroethylene
+ forschungsgemeinschaft
+ deinstitutionalization
+ counterrevolutionaries
+ dehydroepiandrosterone
+ electroencephalography
+ immunoelectrophoresis
+ institutionalisation
+ acetylcholinesterase
+ internationalization
+ institutionalization

+
+

radiopharmaceuticals
+ electroencephalogram
+ keratoconjunctivitis
+ counterrevolutionary
+ immunohistochemistry
+ internationalisation
+ hypercholesterolemia
+ phosphatidylinositol
+ compartmentalization
+ electrophysiological
+ electrocardiographic
+ uncharacteristically

+
+ +
diff --git a/content/font_testing/includes/latin-02/old-nick.htmlpart b/content/font_testing/includes/latin-02/old-nick.htmlpart new file mode 100644 index 0000000..f04580e --- /dev/null +++ b/content/font_testing/includes/latin-02/old-nick.htmlpart @@ -0,0 +1,32 @@ +
+

 

+

If ANYONE wishes to believe me a little loony—which, might be possible, considering that I have quite intentionally made a considerable effort to insinuate that possibility indubitably—may now consider the preceding—as well as the following—proof more or less conclusive. Trust me on this.

+

 

+

The glyph most representative of what 666 is alleged to represent is…$

+

 

+

Why? Because a money-changer (who changes money in the opposite direction from which Jesus would, I figure, do) walked into a temple (in name only; details to follow) which, I suspect, is Christian in name only (doh!), declared that all the money in the temple was Caesar's (if he gets the job and, brother, is Mitt THE right tool for the right job; details to follow), all of which should—again, predicated on the ridiculous notion that I have a clue what Jesus would actually do in any given situation, much less this: if what I can only assume to be true from the so-called reality which ALMOST everyone else on the planet is true, then Jesus has every right to be pissed—as he is alleged to have done in the only “credible” source on the subject, written by profits (this is NOT a typo) who profited ($ or functional equivalent) by peddling every word that they put into the mouth of God is the Absolute Gospel Truth (math majors: prove the inevitability of the conclusions, based on the premises).

+

 

+

And who profits from the word of the prophets who peddle the profits based on the most advantageous “Word of God”?

+

 

+

Who allegedly knew that money only had as much power as you give it (which, according to the Supreme Court—who look nothing like the Supremes, nor as they nearly as smart in ANY sense of the word) is UNLIMITED—simply if you believe it? Who buys every word of it here—every time they get an inkling that the “big money guys” will screw with them…personally, by helping…me?…in ANY way…even to the point of denying me a free beer? Doh! Duh! I still find it amusing.

+

 

+

So, I figure: believe in God (who is Love) or believe in 666, which is $. Each is as real as you believe it to be (welcome to the internet: Marshall MacLuhan WARNED it would be spell-binding). Believe in Heaven on Earth (could it REALLY be ANYWHERE else?); or believe in Hell: right here, right now, QED. Tragedy? Comedy? Happy ending? Or the end of the world? Or believe that loon Ron Paul? John Lennon was pretty much right, every time he opened his mouth—and he wound up dead. So did Jesus—but he had a hell of an out, which I no longer have any credible reason is true, since it’s based on making a profit from people killing themselves as quickly as possible. Devout Muslims score big-time on this one; however, a true believer is a true believer, no matter which words you use—which a true Muslin was so openly joyous when he missed the first chance to share the truths of his heart with someone as nutty as to walk into an Indian restaurant, run by Pakistani Muslims who were fasting for Ramadan but could NOT, UNDER ANY CIRCUMSTANCES accept a NON-ALCOHOLIC—0.0% (Halal++), bought from the corner grocery the owner’s Muslim brother ran and have the temerity to ask anyone to not share a beer in exchanging for confessing the things his heart which he believes to be ABSOLUTELY TRUE…

+

 

+

Well, imagine my joy on such a chance (not a chance) meeting in which we placed our hands on each other’s hearts and testified…

+

 

+

Precisely the same words, except…I did so in English, and he did so in Urdu (lucky for me, you and the whole world, potentially), only in different words. Duh. Doh. Uh-oh.

+

 

+

God gave you free will: exercise and create the future, or relive the past (Go, George Santayana!). If you have been paying attention, I have given you no choice: toast my old man in Wilwaukee and take the pledge (available online—if you can find it), or the world ends…your $666$ way. Who are you going to believe? Well, if Lozos will deliver the rimshot: me. If you can’t take a joke, I am dying anyway. Which is inevitable and hopeless—unless it isn’t and Alan Watts is right. And if NOBODY can take this joke…the punchline is inevitable eight ways to Sunday: cash, credit, as unreal as possible (preferably ACH!!!), but only Amex under very special circumstances…like, when Hell freezes over.

+

 

+

P.S. As soon as lightning strikes twice in the same place (God only know that) at some time (ditto), either Cassandra (probably) or Tinkerbelle (I hope) will get the predicted ending. Scholarly folk: clue them in and, in this context, the context of the former is important, because the context is actually where reality started getting taken out of context, which is reality—precisely as nature intended it.

+

 

+

Make a copy quick: Western Civilization is going down if I, personally, as God has made abundantly clear through his one and only non-profit prophet (I did not ask for this job) if one sober person in this joint will not at least OFFER to buy me a beer, for fear of pissing off the big money which exists only because you believe in money, but you do not believe in Love. Or free beer. No joke. Seriously.

+

 

+

 

+

P.S. In case anyone doubts that I might have reason to be paranoid.

+

On paper is still real; going viral is not confined to the internet. I got back-up: Army, Navy, former Maximum Security Prison guard, regular folks, large muscular black men, dogs, regular folk—peppered all over. Take us all on (you MAY already know who they are) if you can find them (disregard previous message), or wipe us all out.

+

Caution: Mormon virgins nearby. Sacrifice them and PROVE just how barbaric you aren't. Even if this message never actually reaches the internet (I firmly believe that almost anything is possible, but prefer to assign as little credibility to the uncomfortable stuff, unless given credible reason to believe so), it got through to the right folks. If so, wipe us out—I have made a pretty good case where the impossible might inevitably happen, only now the time is the only issue. Proofs of this promise supposedly existed in the White House when I tossed it out. If it turns up not to be there, tell me something I might not have anticipated. Because what I don't know will, in fact kill me—but (yo, Fred) what does not kill me…

+

Pray I am wrong and I am dead. Pray I am right, and do it the right way—to God, who must necessarily exist in order to pray. Doh!

+

Rimshot, dammit! Or gunshot. Or freak lightning from nowhere, or plausible probability of something kinda like it. I did ask for it, didn't I? Language people: decipher this before 666 does...

+ +
diff --git a/content/font_testing/includes/latin-02/ruder.htmlpart b/content/font_testing/includes/latin-02/ruder.htmlpart new file mode 100644 index 0000000..89c712c --- /dev/null +++ b/content/font_testing/includes/latin-02/ruder.htmlpart @@ -0,0 +1,56 @@ +
+ +

32px Text.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
vertragcraintescrew bibelmalhabilemodo
verwaltercroyantscience biegenpeuplepunibile
verzichtfratricidesketchy blindqualifierquindi
vorredefrivolitéstory damalsquelledinamica
yankeeinstructiontake chinaquelqueanaliso
zwetschgelyretreaty schadensalomonmacchina
zypressenavettetricycle scheinselliersecondo
frakturnocturnetypograph lagersommiersingolo
kraftpervertirvanity legionuniquepossibile
raffelnprestovictory mimeunanimeunico
reaktionprévoyantvivacity mohnusuellegge
rekordprioritéwayward nagelabonnerunione
revolteproscrireefficiency puderagirpunizione
trittraviverwithout quälenaiglondunque
trotzkopftactilitéthrough huldigenallégirquando
tyrannarrêtknown geduldallianceuomini
+
diff --git a/content/font_testing/includes/latin-02/stephenson-blake.htmlpart b/content/font_testing/includes/latin-02/stephenson-blake.htmlpart new file mode 100644 index 0000000..eb109aa --- /dev/null +++ b/content/font_testing/includes/latin-02/stephenson-blake.htmlpart @@ -0,0 +1,28 @@ +
+ +

Stephenson Blake Testing Sheet - 32px

+

+ COMMOONWEALTH? WARWICKSHIRE; BALACLAVAH!
+ BIRMINGHAM OSSORY'S MUZZLEM ENJOYMÆNTS
+ SUPPROSSŒNS LIVEERPOOL SOCIETIES QURQUHARTS
+ SHEFFIELD UNITED: VECCHI-HINTTING
+
+ HHAAHBBHCCHDDHEEHFFHGGHIIHJJHKKHLLHMMH
+ HNNHOOHPPHQQHRRHSSHTTHUUHVVHWWHXXH
+ HYYHZZHÆÆHŒŒH&c.,&c.      HHOOH. nnoon.
+
+ hammond; welchpool: carboniferous! weed-haarlem hoddledop
+ moggorton's divines excelent quinquennial ixias maccabees
+ commoonwealth? tarquin possessions patriarchs inflame
+ muzzlem (sanctified) deschæpeles sumœtra nwaveyn
+
+ nnaanbbnccnddneenffnggnhhniinjjnkknllnmmnoon
+ nppnqqnrrnssnttnuunvvnwwnxxnyynzznæænœœn
+ nfifinflflnffffnffiffinfflffln&c.,&c.     November 26th, 1958
+
+ nn,,n..n::n--n     HH!!H??H‘H’H“H”H
+
+ £00110220330440550660770880990£
+ $03192834754159261483759171$

+ +
\ No newline at end of file diff --git a/content/font_testing/includes/latin/constants-latin.json b/content/font_testing/includes/latin/constants-latin.json new file mode 100644 index 0000000..3f5b189 --- /dev/null +++ b/content/font_testing/includes/latin/constants-latin.json @@ -0,0 +1,82 @@ +{ + "GRUMPIES": { + "short": { + "text": "Grumpy wizards make toxic brew for the evil Queen and Jack. A quick movement of the enemy will jeopardize six gunboats. The job of waxing linoleum frequently peeves chintzy kids. My girl wove six dozen plaid jackets before she quit. Twelve ziggurats quickly jumped a finch box.", + "columns": [ + { + "sizes": [96, 84, 72, 60, 48, 36, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12] + } + ] + }, + + "long": { + "text": "Grumpy wizards make toxic brew for the evil Queen and Jack. One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. 01234567890 ", + "columns": [ + {"sizes": [20, 19, 18, 17]}, + {"sizes": [16, 15, 14, 13, 12, 11, 10]} + ] + }, + + "lowercaseShort": { + "text": "the five boxing wizards jump quickly pack my red box with five dozen quality jugs a very big box sailed up then whizzed quickly from japan", + "columns": [ + {"sizes": [96, 84, 72, 60, 48, 36, 30, 24, 18]} + ] + }, + + "lowercaseLong": { + "text": "serviced tightly trestle custom nosey impugned gooier deeper oat charade smashed welting clopping fondly discard welfare gaudy mission shoddily mooed knelling glance golfed trope togae knocked vulgarly gigabyte curbing snowball outback stepped marmot clayier coltish descry gratify root freedom puree urgency moist careered journal oracle felony marble salary readying besiege twitched ranching snoozing disk mister warbling outwit schism sudsiest street gondola blushing pennon smarted jiving sty rocker griping rocketry dieing tarring A very big box sailed up then whizzed quickly from Japan the five boxing wizards jump quickly pack my red box with five dozen quality jugs", + "columns": [ + {"sizes": [16, 15, 14]}, + {"sizes": [13, 12, 11, 10]} + ] + }, + + "adhesionShort": { + "text": "adhesion donnishness indianians deaden on ode so sheenie died dashed dens seaside easines nonseasoned seen hindi said seines sadnesses deaden donnishness dissensions dead", + "columns": [ + {"sizes": [96, 84, 72, 60, 48, 36, 30, 24, 18]} + ] + }, + + "adhesionLong": { + "text": "dined shoon hooded ahead shined hashed dinned soon nod nine sane inned ani session doe node idea side indeed aide anise hose noose noshed inside hid aeon inane none hoed nosed diseased handed noise haded sanded one hie deeded shine honed disdained hen ash said hah onion sodded donned and aha dine disease deed adenoid hoodooed deaned end denied anon iodine nosh shooed deadened sided addenda did aniseed sand hied nodded nose shoeshine hashish hissed done seed noon sensed sinned needed send nooned odd disdain shinned anion had shied", + "columns": [ + {"sizes": [16, 15, 14]}, + {"sizes": [13, 12, 11, 10]} + ] + }, + + "hamburgefonstivShort": { + "text": "fortieth boring trait favoring barrage referring thrusting tannest embargo sausage gaining astutest augur hibernate variant hearse beggaring foresee eagerer hearten ensnaring tufting interstate meager veneration stigma feminine tabbing noising trimming throbbing ransoming stiffen oaring fishing rehire overbore bonniest ravishment teensiest mintier shriven unforeseen overrate surgeon smarter submarine revenging assuaging masher amnesia insentient rehashing fresher buttering sorghum thine sitter month serer minting variate torsion gaunt", + "columns": [ + {"sizes": [96, 84, 72, 60, 48, 36, 30, 24, 18]} + ] + }, + + "hamburgefonstivLong": { + "text": "fortieth boring trait favoring barrage referring thrusting tannest embargo sausage gaining astutest augur hibernate variant hearse beggaring foresee eagerer hearten ensnaring tufting interstate meager veneration stigma feminine tabbing noising trimming throbbing ransoming stiffen oaring fishing rehire overbore bonniest ravishment teensiest mintier shriven unforeseen overrate surgeon smarter submarine revenging assuaging masher amnesia insentient rehashing fresher buttering sorghum thine sitter month serer minting variate torsion gaunt berthing goofiest sober informing sourer tonight neigh iratest torte situate rheumier antagonist serening motion guise unseeing masseuse", + "columns": [ + {"sizes": [16, 15, 14]}, + {"sizes": [13, 12, 11, 10]} + ] + }, + + "caps": { + "text": "Arrowroot Barley Chervil Dumpling Endive Flaxseed Garbanzo Hijiki Ishtu Jicama Kale Lychee Marjoram Nectarine Oxtail Pizza Quinoa Roquefort Squash Tofu Uppuma Vanilla Wheat Xergis Yogurt Zweiback 0 1 2 3 4 5 6 7 8 9 ! ?", + "columns": [ + {"sizes": [60, 48, 36, 30, 28, 24, 20, 18, 16, 14, 13]} + ] + }, + "allcaps": { + "text": "ARROWROOT BARLEY CHERVIL DUMPLING ENDIVE FLAXSEED GARBANZO HIJIKI ISHTU JICAMA KALE LYCHEE MARJORAM NECTARINE OXTAIL PIZZA QUINOA ROQUEFORT SQUASH TOFU UPPUMA VANILLA WHEAT XERGIS YOGURT ZWEIBACK 0 1 2 3 4 5 6 7 8 9 ! ?", + "columns": [ + {"sizes": [60, 48, 36, 30, 28, 24, 20, 18, 16, 14, 13]} + ] + } + } +, "hintsSizes": [28, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 16, 15, 14, 13, 12, 11, 10, 9] +, "hintsCaps": "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +, "hintsLower": "abcdefghijklmnopqrstuvwxyz.:;," +, "hintsNumbers": "1234567890 @ &!?#$€%" +} diff --git a/content/font_testing/includes/latin/diatrics.htmlpart b/content/font_testing/includes/latin/diatrics.htmlpart new file mode 100644 index 0000000..a65c417 --- /dev/null +++ b/content/font_testing/includes/latin/diatrics.htmlpart @@ -0,0 +1,174 @@ +
+ +

GF Latin Plus

+

À Á Â Ã Ä Å Ā Ă Ą Ǻ Ȁ Ȃ Ạ Æ Ǽ Ć Ç Ĉ Ċ Č Ď Đ Ð È É Ê Ë Ē Ĕ Ė Ę Ẽ Ě Ẹ Ȅ Ȇ Ə Ĝ Ğ Ġ Ģ Ǧ Ĥ Ħ Ĭ Ì Í Î Ï İ Ĩ Ī Į Ị Ȉ Ȋ Ĵ Ķ Ĺ Ļ Ľ Ŀ Ł Ñ Ń Ņ Ň Ŋ Ò Ó Ô Õ Ö Ø Ō Ŏ Ő Ǿ Ǫ Ọ Ȫ Ȱ Ȭ Ȍ Ȏ Œ Þ Ŕ Ŗ Ř Ȑ Ȓ Ś Ŝ Š Ș Ş ẞ Ŧ Ť Ț Ţ Ù Ú Û Ü Ũ Ū Ŭ Ů Ű Ų Ụ Ȕ Ȗ Ẁ Ẃ Ẅ Ŵ Ý Ŷ Ÿ Ỳ Ỹ Ȳ Ź Ż Ž

+

à á â ã ä å ā ă ą ǻ ȁ ȃ ạ æ ǽ ć ç ĉ ċ č ď đ ð è é ê ë ē ĕ ė ę ě ẽ ẹ ȅ ȇ ə ĝ ğ ġ ģ ǧ ĥ ħ ì í î ï ĩ ī į ĭ ị ȉ ȋ ı ĵ ȷ ķ ĸ ĺ ļ ľ ŀ ł ń ņ ň ñ ŋ ò ó ô õ ö ø ō ŏ ő ǿ ǫ ọ ȍ ȏ ȫ ȱ ȭ œ þ ŕ ŗ ř ȑ ȓ ś ŝ š ș ş ß ŧ ť ț ţ ù ú û ü ũ ū ŭ ů ű ų ụ ȕ ȗ ẁ ẃ ẅ ŵ ý ÿ ŷ ỳ ỹ ȳ ź ż ž

+

 

+ +

GF Latin Plus Vietnamese

+

Á Ă Ắ Ặ Ằ Ẳ Ẵ Â Ấ Ậ Ầ Ẩ Ẫ Ạ À Ả Ã Đ É Ê Ế Ệ Ề Ể Ễ Ẹ È Ẻ Ẽ Í Ị Ì Ỉ Ĩ Ó Ô Ố Ộ Ồ Ổ Ỗ Ọ Ò Ỏ Ơ Ớ Ợ Ờ Ở Ỡ Õ Ú Ụ Ù Ủ Ư Ứ Ự Ừ Ử Ữ Ũ Ý Ỵ Ỳ Ỷ Ỹ

+

á ă ắ ặ ằ ẳ ẵ â ấ ậ ầ ẩ ẫ ạ à ả ã đ é ê ế ệ ề ể ễ ẹ è ẻ ẽ í ị ì ỉ ĩ ó ô ố ộ ồ ổ ỗ ọ ò ỏ ơ ớ ợ ờ ở ỡ õ ú ụ ù ủ ư ứ ự ừ ử ữ ũ ý ỵ ỳ ỷ ỹ

+

 

+ +

GF Latin Pro

+

Ḉ Ḍ Ḏ Ḕ Ḗ Ḝ Ḡ Ḥ Ḫ Ḯ Ḷ Ḻ Ṃ Ṅ Ṇ Ṉ Ṍ Ṏ Ṑ Ṓ Ṛ Ṟ Ṡ Ṣ Ṥ Ṧ Ṩ Ṭ Ṯ Ṹ Ṻ Ẏ Ẓ

+

ḉ ḍ ḏ ḕ ḗ ḝ ḡ ḥ ḫ ḯ ḷ ḻ ṃ ṅ ṇ ṉ ṍ ṏ ṑ ṓ ṛ ṟ ṡ ṣ ṥ ṧ ṩ ṭ ṯ ẗ ṹ ṻ ẏ ẓ

+

 

+ + +

Azeri

+

Zəfər, jaketini də papağını da götür, bu axşam hava çox soyuq olacaq.

 

+ +

Catalan

+

Jove xef, porti whisky amb quinze glaçons d'hidrogen, coi!

 

+ +

Croatian

+

Gojazni đačić s biciklom drži hmelj i finu vatu u džepu nošnje.

 

+ +

Czech

+

Nechť již hříšné saxofony ďáblů rozzvučí síň úděsnými tóny waltzu, tanga a quickstepu

 

+ +

Danish

+

Høj bly gom vandt fræk sexquiz på wc

 

+ +

Dutch

+

Lynx c.q. vos prikt bh: dag zwemjuf!

 

+ +

Esperanto

+

Eble ĉiu kvazaŭ-deca fuŝĥoraĵo ĝojigos homtipon

 

+ +

Estonian

+

Põdur Zagrebi tšellomängija-följetonist Ciqo külmetas kehvas garaažis

 

+ +

Filipino

+

Ang buko ay para sa tao dahil wala nang pwedeng mainom na gatas.

 

+ +

Finnish

+

Törkylempijävongahdus Albert osti fagotin ja töräytti puhkuvan melodian

 

+ +

French

+

Buvez de ce whisky que le patron juge fameux

 

+ +

West Frisian

+

Alve bazige froulju wachtsje op dyn komst

 

+ +

German

+

Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich

 

+ +

Hungarian

+

Jó foxim és don Quijote húszwattos lámpánál ülve egy pár bűvös cipőt készít

 

+ +

Icelandic

+

Kæmi ný öxi hér, ykist þjófum nú bæði víl og ádrepa.

 

+ +

Irish

+

D'fhuascail Íosa Úrmhac na hÓighe Beannaithe pór Éava agus Ádhaimh

 

+ +

Italian

+

In quel campo si trovan funghi in abbondanza.

 

+ +

Latvian

+

Muļķa hipiji turpat brīvi mēģina nogaršot celofāna žņaudzējčūsku.

 

+ +

Lithuanian

+

Įlinkdama fechtuotojo špaga sublykčiojusi pragręžė apvalų arbūzą

 

+ +

Norwegian

+

Vår sære Zulu fra badeøya spilte jo whist og quickstep i min taxi.

 

+ +

Polish

+

Jeżu klątw, spłódź Finom część gry hańb!

 

+ +

Portuguese

+

Luís argüia à Júlia que «brações, fé, chá, óxido, pôr, zângão» eram palavras do português.

 

+ +

Romanian

+

Muzicologă în bej vând whisky și tequila, preț fix.

 

+ +

Serbian (also applies to Croatian and Bosnian)

+

Gojazni đačić s biciklom drži hmelj i finu vatu u džepu nošnje.

 

+ +

Slovak

+

Kŕdeľ ďatľov učí koňa žrať kôru.

 

+ +

Slovenian

+

Šerif bo za vajo spet kuhal domače žgance. Piškur molče grabi fižol z dna cezijeve hoste.

 

+ +

Spanish

+

El veloz murciélago hindú comía feliz cardillo y kiwi. ¡qué figurota exhibe! La cigüeña tocaba el saxofón ¿Detrás del palenque de paja?

 

+ +

Swedish

+

Yxskaftbud, ge vår WC-zonmö IQ-hjälp.

 

+ +

Turkish

+

Fahiş bluz güvencesi yağdırma projesi çöktü.

 

+ + +
+ +

Albanian

+

Mbasi njohja e dinjitetit të lindur të të drejtave të barabarta dhe të patjetërsueshme të të gjithë anëtarëve të familjes njerëzore është themeli i lirisë, drejtësisë dhe paqes në botë; mbasi mosrespektimi dhe përbuzja e të drejtave të njeriut ka cuar drejt akteve barbare, të cilat kanë ofenduar ndërgjegjen e njerëzimit, dhe mbasi krijimi i botës në të cilën njerëzit do të gëzojnë lirinë e fjalës, të besimit dhe lirinë nga frika e skamja është proklamuar si dëshira më e lartë e cdo njeriu; mbasi është e nevojshme që të drejtat e njeriut të mbrohen me dispozita juridike, kështu që njeriu të mos jetë i shtrënguar që në pikën e fundit t’i përvishet kryengritjes kundër tiranisë dhe shtypjes; mbasi është e nevojshme që të nxitet zhvillimi i marrëdhënieve miqësore midis kombeve; mbasi popujt e Kombeve të Bashkuara vërtetuan përsëri në Kartë besimin e tyre në të drejtat themelore të njeriut, në dinjitetin dhe vlerën e personit të njeriut dhe barazinë midis burrave dhe grave dhe mbasi vendosën që të nxitin përparimin shoqëror dhe të përmirësojnë nivelin e jetës në liri të plotë; mbasi shtetet anëtare u detyruan që, në bashkëpunim me Kombet

 

+ +

Dutch (Nederlands)

+

Overwegende, dat erkenning van de inherente waardigheid en van de gelijke en onvervreemdbare rechten van alle leden van de mensengemeenschap grondslag is voor de vrijheid, gerechtigheid en vrede in de wereld; overwegende, dat terzijdestelling van en minachting voor de rechten van de mens geleid hebben tot barbaarse handelingen, die het geweten van de mensheid geweld hebben aangedaan en dat de komst van een wereld, waarin de mensen vrijheid van meningsuiting en geloof zullen genieten, en vrij zullen zijn van vrees en gebrek, is verkondigd als het hoogste ideaal van iedere mens; overwegende, dat het van het grootste belang is, dat de rechten van de mens beschermd worden door de suprematie van het recht, opdat de mens niet gedwongen worde om in laatste instantie zijn toevlucht te nemen tot opstand tegen tyrannie en onderdrukking; overwegende, dat het van het grootste belang is om de ontwikkeling van vriendschappelijke betrekkingen tussen de naties te bevorderen; overwegende, dat de volkeren van de Verenigde Naties in het Handvest hun vertrouwen in de fundamentele rechten van de

 

+ +

Estonian

+

Pidades silmas, et inimkonna kõigi liikmete väärikuse, nende võrdsuse ning võõrandamatute õiguste tunnustamine on vabaduse, õigluse ja üldise rahu alus; ja pidades silmas, et inimõiguste põlastamine ja hülgamine on viinud barbaarsusteni, mis piinavad inimkonna südametunnistust, ja et sellise maailma loomine, kus inimestel on veendumuste ja sõnavabadus ning kus nad ei tarvitse tunda hirmu ega puudust, on inimeste üllaks püüdluseks kuulutatud; ja pidades silmas vajadust, et inimõigusi kaitseks seaduse võim selleks, et inimene ei oleks sunnitud viimase abinõuna üles tõusma türannia ja rõhumise vastu; ja pidades silmas, et on vaja kaasa aidata sõbralike suhete arendamisele rahvaste vahel ja; pidades silmas,et ühinenud rahvaste perre kuuluvad rahavad on põhikirjas kinnitanud oma usku inimese põhiõigustesse, inimisiksuse väärikusse ja väärtusse ning meeste ja naiste võrdõiguslikkusesse ning on otsustanud kaasa aidata sotsiaalsele progressile ja elutingimuste parandamisele suurema vabaduse juures; ja pidades silmas,et liikmesriigid on kohustatud koostöös Ühinenud Rahvaste

 

+ +

Finnish (Suomi)

+

Kun ihmiskunnan kaikkien jäsenten luonnollisen arvon ja heidän yhtäläisten ja luovuttamattomien oikeuksiensa tunnustaminen on vapauden, oikeudenmukaisuuden ja rauhan perustana maailmassa, kun ihmisoikeuksia on väheksytty tai ne on jätetty huomiota vaille, on tapahtunut raakalaistekoja, jotka ovat järkyttäneet ihmiskunnan omaatuntoa, ja kun kansojen korkeimmaksi päämääräksi on julistettu sellaisen maailman luominen, missä ihmiset voivat vapaasti nauttia sanan ja uskon vapautta sekä elää vapaina pelosta ja puutteesta, kun on välttämätöntä, että ihmisoikeudet turvataan oikeusjärjestyksellä, jotta ihmisten ei olisi pakko viimeisenä keinona nousta kapinaan pakkovaltaa ja sortoa vastaan, kun on tähdellistä edistää ystävällisten suhteiden kehittymistä kansojen välille, kun Yhdistyneiden Kansakuntien kansat ovat peruskirjassa vahvistaneet uskonsa ihmisten perusoikeuksiin, ihmisyksilön arvoon ja merkitykseen sekä miesten ja naisten yhtäläisiin oikeuksiin ja kun ne ovat ilmaisseet vakaan tahtonsa edistää sosiaalista kehitystä ja parempien elämisen ehtojen aikaansaamista vapaammissa oloissa

 

+ +

French (Français)

+

Considérant que la reconnaissance de la dignité inhérente à tous les membres de la famille humaine et de leurs droits égaux et inaliénables constitue le fondement de la liberté, de la justice et de la paix dans le monde, considérant que la méconnaissance et le mépris des droits de l’homme ont conduit à des actes de barbarie qui révoltent la conscience de l’humanité et que l’avènement d’un monde où les êtres humains seront libres de parler et de croire, libérés de la terreur et de la misère, a été proclamé comme la plus haute aspiration de l’homme, considérant qu’il est essentiel que les droits de l’homme soient protégés par un régime de droit pour que l’homme ne soit pas contraint, en suprême recours, à la révolte contre la tyrannie et l’oppression, considérant qu’il est essentiel d’encourager le développement de relations amicales entre nations, considérant que dans la charte les peuples des Nations Unies ont proclamé à nouveau leur foi dans les droits fondamentaux de l’homme, dans la dignité et la valeur de la personne humaine, dans l’égalité des droits des hommes et des femmes, et qu’ils se sont déclarés résolus à favoriser le progrès social

 

+ +

German (Deustsch)

+

Da die Anerkennung der angeborenen Würde und der gleichen und unveräußerlichen Rechte aller Mitglieder der Gemeinschaft der Menschen die Grundlage von Freiheit, Gerechtigkeit und Frieden in der Welt bildet, da die Nichtanerkennung und Verachtung der Menschenrechte zu Akten der Barbarei geführt haben, die das Gewissen der Menschheit mit Empörung erfüllen, und da verkündet worden ist, daß einer Welt, in der die Menschen Rede- und Glaubensfreiheit und Freiheit von Furcht und Not genießen, das höchste Streben des Menschen gilt, da es notwendig ist, die Menschenrechte durch die Herrschaft des Rechtes zu schützen, damit der Mensch nicht gezwungen wird, als letztes Mittel zum Aufstand gegen Tyrannei und Unterdrückung zu greifen, da es notwendig ist, die Entwicklung freundschaftlicher Beziehungen zwischen den Nationen zu fördern, da die Völker der Vereinten Nationen in der Charta ihren Glauben an die grundlegenden Menschenrechte, an die Würde und den Wert der menschlichen Person und an die Gleichberechtigung von Mann und Frau erneut bekräftigt und beschlossen haben, den sozialen

 

+ +

Hungarian

+

Tekintettel arra, hogy az emberiség családja minden egyes tagja méltóságának, valamint egyenlő és elidegeníthetetlen jogainak elismerése alkotja a szabadság, az igazság és a béke alapját a világon, tekintettel arra, hogy az emberi jogok el nem ismerése és semmibevevése az emberiség lelkiismeretét fellázító barbár cselekményekhez vezetett, és hogy az ember legfőbb vágya egy olyan világ eljövetele, amelyben az elnyomástól, valamint a nyomortól megszabadult emberi lények szava és meggyőződése szabad lesz, tekintettel annak fontosságára, hogy az emberi jogokat a jog uralma védelmezze, nehogy az ember végső szükségében a zsarnokság és az elnyomás elleni lázadásra kényszerüljön, tekintettel arra, hogy igen lényeges a nemzetek közötti baráti kapcsolatok kifejeződésének előmozdítása, tekintettel arra, hogy az Alapokmányban az Egyesült Nemzetek népei újból hitet tettek az alapvető emberi jogok, az emberi személyiség méltósága és értéke, a férfiak és nők egyenjogúsága mellett, valamint kinyilvánították azt az elhatározásukat, hogy elősegítik a szociális haladást és nagyobb szabadság mellett

 

+ +

Icelandic (Íslenska)

+

Það ber að viðurkenna, að hver maður sé jafnborinn til virðingar og réttinda, er eigi verði af honum tekin, og er þetta undirstaða frelsis, réttlætis og friðar i heiminum. Hafi mannréttindi verið fyrir borð borin og lítilsvirt, hefur slíkt haft í för með sér siðlausar athafnir, er ofboðið hafa samvizku mannkynsins, enda hefur því verið yfir lýst, að æðsta markmið almennings um heim allan sé að skapa veröld, þar sem menn fái notið málfrelsis, trúfrelsis og óttaleysis um einkalíf afkomu. Mannréttindi á að vernda með lögum. Að öðrum kosti hljóta menn að grípa til þess örþrifaráðs að rísa upp gegn kúgun og ofbeldi. Það er mikilsvert að efla vinsamleg samskipti þjóða í milli. Í stofnskrá sinni hafa Sameinuðu þjóðdirnar lýst yfir trú sinni á grundvallaratriði mannréttinda, á göfgi og gildi mannsins og jafnrétti karla og kvernna, enda munu þær beita sér fyrir félagslegum framförum og betri lífsafkomu með auknu frelsi manna. Aðildarríkin hafa bundizt samtökum um að efla almenna virðingu fyrir og gæzlu hinna mikilsverðustu mannréttinda í samráði við Sameinuðu þjóðirnar. Til þess að slík samtök megi sem

 

+ +

Irish

+

De Bhrí gurb é aithint dínte dúchais agus chearta comhionanna do-shannta an uile dhuine den chine daonna is foras don tsaorise, don cheartas agus don tsíocháin sa domhan, de Bhrí gur thionscain a neamhaird agus an mí-mheas ar chearta an duine gníomhartha barbartha a chuir uafás ar choinsias an chine daonna, agus go bhfuil forógartha gurb é meanmarc is uaisle ag an gcoitiantacht saol a thabhairt i réim a bhéarfas don duine saoirse chainte agus chreidimh agus saoirse ó eagla agus ó amhgar, de Bhrí go ndearna pobail na Náisiúin Aontaithe sa Chairt dearbhú athuair ar a gcreideamh i gcearta bunúsacha an duine, i ndínit agus i bhfiúntas pearsan an duine agus i gcearta comhionanna fear agus bean, agus gur chinneadar tacú leis an ascnamh sóisalach agus réim maireachtana níos fearr a thabhairt i gcrích faoi shaoirse níos fairsinge, de Bhrí gur ghabhadar na Stát-Chomhaltaí faoi chuing ghealltanais go ndéanfaid, i gcomhar leis na Náisiúin Aontaithe, urraim uile-choiteann éifeachtach d’áirithiú do chearta agus do shaoirsí bunúsacha an duine. De Bhrí go bhfuil sé fíor-thábhachtach, chun an

 

+ +

Italian

+

Considerato che il riconoscimento della dignità inerente a tutti i membri della famiglia umana e dei loro diritti, uguali ed inalienabili, costituisce il fondamento della libertà, della giustizia e della pace nel mondo; considerato che il disconoscimento e il disprezzo dei diritti umani hanno portato ad atti di barbarie che offendono la coscienza dell’umanità, e che l’avvento di un mondo in cui gli esseri umani godano della libertà di parola e di credo e della libertà dal timore e dal bisogno è stato proclamato come la più alta aspirazione dell’uomo; considerato che è indispensabile che i diritti umani siano protetti da norme giuridiche, se si vuole evitare che l’uomo sia costretto a ricorrere, come ultima istanza, alla ribellione contro la tirannia e l’oppressione; considerato che è indispensabile promuovere lo sviluppo di rapporti amichevoli tra le Nazioni; considerato che i popoli delle Nazioni Unite hanno riaffermato nello Statuto la loro fede nei diritti umani fondamentali, nella dignità e nel valore della persona umana, nell’uguaglianza dei diritti dell’uomo e della donna, ed hanno deciso di promuovere il progresso sociale e un miglior tenore di vita in

 

+ +

Lithuanian

+

Kadangi visų žmonių giminės narių prigimtinio orumo ir lygių bei neatimamų teisių pripažinimas yra laisvės, teisingumo ir taikos pasaulyje pagrindas; kadangi žmogaus teisių nepaisymas ir niekinimas pastūmėjo vykdyti barbariškus aktus, kurie papiktino žmonijos sąžinę, ir didžiausiu paprastų žmonių siekiu buvo paskelbtas pasaulio, kuriame žmonės turi žodžio bei įsitikinimų laisvę ir yra išlaisvinti iš baimės ir skurdo, sukūrimas; kadangi būtina, kad žmogaus teises saugotų įstatymo galia, idant žmogus nebūtų priverstas, nerasdamas jokios kitos išeities, sukilti prieš tironiją ir priespaudą; kadangi būtina skatinti draugiškų tautų santykių plėtrą; kadangi Jungtinių Tautų Chartijoje tautos vėl patvirtino savo tikėjimą pagrindinėmis žmogaus teisėmis, žmogaus, kaip asmenybės, orumu ir vertybe, lygiomis moterų ir vyrų teisėmis ir pasiryžo skatinti socialinę pažangą bei geresnio gyvenimo didesnės laisvės sąlygomis siekį; kadangi valstybės narės yra įsipareigojusios bendradarbiaudamos su Jungtinėmis Tautomis siekti, kad būtų skatinama visuotinė pagarba žmogaus teisėms ir pagrindinėms laisvėms ir jų būtų paisoma; kadangi bendras šių teisių ir laisvių supratimas yra nepaprastai svarbus.

 

+ +

Norwegian, Bokmål (Norsk)

+

Da anerkjennelsen av menneskeverd og like og umistelige rettigheter for alle medlemmer av menneskeslekten er grunnlaget for frihet, rettferdighet og fred i verden, da tilsidesettelse av og forakt for menneskerettighetene har ført til barbariske handlinger som har rystet menneskehetens samvittighet, og da framveksten av en verden hvor menneskene har tale- og trosfrihet og frihet fra frykt og nød, er blitt kunngjort som folkenes høyeste mål, da det er nødvendig at menneskerettighetene blir beskyttet av loven for at menneskene ikke skal tvinges til som siste utvei å gjøre opprør mot tyranni og undertrykkelse, da det er viktig å fremme utviklingen av vennskapelige forhold mellom nasjonene, da De Forente Nasjoners folk i Pakten på ny har bekreftet sin tro på grunnleggende menneskerettigheter, på menneskeverd og på like rett for menn og kvinner og har besluttet å arbeide for sosialt framskritt og bedre levevilkår under større Frihet, da medlemsstatene har forpliktet seg til i samarbeid med De Forente Nasjoner å sikre at menneskerettighetene og de grunnleggende friheter blir alminnelig respektert og overholdt, da en allmenn

 

+ +

Polish (Polski)

+

Zważywszy, że uznanie przyrodzonej godności oraz równych i niezbywalnych praw wszystkich członków wspólnoty ludzkiej jest podstawą wolności, sprawiedliwości i pokoju świata, zważywszy, że nieposzanowanie i nieprzestrzeganie praw człowieka doprowadziło do aktów barbarzyństwa, które wstrząsnęły sumieniem ludzkości, i że ogłoszono uroczyście jako najwznioślejszy cel ludzkości dążenie do zbudowania takiego świata, w którym ludzie korzystać będą z wolności słowa i przekonań oraz z wolności od strachu i nędzy, zważywszy, że konieczne jest zawarowanie praw człowieka przepisami prawa, aby nie musiał—doprowadzony do ostateczności—uciekać się do buntu przeciw tyranii i uciskowi, zważywszy, że konieczne jest popieranie rozwoju przyjaznych stosunków między narodami, zważywszy, że Narody Zjednoczone przywróciły swą wiarę w podstawowe prawa człowieka, godność i wartość jednostki oraz w równouprawnienie mężczyzn i kobiet, oraz wyraziły swe zdecydowanie popierania postępu społecznego i poprawy warunków życia w większej wolności, zważywszy, że Państwa Członkowskie

 

+ +

Portuguese

+

Considerando que o reconhecimento da dignidade inerente a todos os membros da família humana e dos seus direitos iguais e inalienáveis constitui o fundamento da liberdade, da justiça e da paz no mundo; considerando que o desconhecimento e o desprezo dos direitos do Homen conduziram a actos de barbárie que revoltam a consciência daHumanidade e que o advento de um mundo em que os seres humanos sejam livres de falar e de crer, libertos do terror e da miséria, foi proclamado como a mais alta inspiração do Homem; considerando que é essencial a proteção dos direitos do Homem através de um regime de direito, para que o Homem não seja compelido, em supremo recurso, à revolta contra a tirania e a opressão; considerando que é essencial encorajar o desenvolvimento de relações amistosas entre as nações; considerando que, na Carta, os povos das Nações Unidas proclamam, de novo, a sua fé nos direitos fundamentais do Homem, na dignidade e no valor da pessoa humana, na igualdade de direitos dos homens e das mulheres e se declaram resolvidos a favorecer o progresso social e a instaurar melhores condições

 

+ +

Romanian (Româna)

+

Considerînd că recunoașterea demnității inerente tuturor membrilor familiei umane și a drepturilor lor egale și inalienabile constituie fundamentul libertății, dreptății și păcii în lume, considerînd că ignorarea și disprețuirea drepturilor omului au dus la acte de barbarie care revoltă conștiința omenirii și că făurirea unei lumi în care ființele umane se vor bucura de libertatea cuvîntului și a convingerilor și vor fi eliberate de teamă și mizerie a fost proclamată drept cea mai înaltă aspirație a oamenilor, considerînd că este esențial ca drepturile omului să fie ocrotite de autoritatea legii pentru ca omul să nu fie silit să recurgă, ca soluție extremă, la revoltă împotriva tiraniei și asupririi, considerînd că este esențial a se încuraja dezvoltarea relațiilor prietenești între națiuni, considerînd că în Cartă popoarele Organizației Națiunilor Unite au proclamat din nou credința lor în drepturile fundamentale ale omului, în demnitatea și în valoarea persoanei umane, drepturi egale pentru bărbați și femei și că au hotărît să favorizeze progresul social și îmbunătățirea condițiilor de viață în cadrul unei libertăți mai mari, considerînd că statele membre s-au

 

+ +

Slovak (Slovencina)

+

Vo vedomí že uznanie prirodzenej dôstojnosti a rovnych a neodcudzite ľných práv členov ľudskej rodiny je základom slobody, spravodlivosti a mieru na svete, že zneuznanie ľudských práv a pohrdanie nimi viedlo k barbarským činom, ktoré urážajú svedomie ľudstva, a že vybudovanie sveta, v ktorom ľudia, zbavení strachu a núdze, budú sa tešiť slobode prejavu a presvedčenia, bolo vyhlásené za najvyšší cieľ ľudu, že je nutné, aby sa ľudsk práva chránily zákonom, ak nemá byť človek donúteý uchýliť sa, keď všetko ostatné zlyhalo, k odboju proti tyranii a útlaku, že je nutné podporovať rozvoj priateľských vzťahov medzi národmi, že ľud Spojených národov zdoraznil v Charte znovu svoju vieru v základné ľudské práva, v dostojnosť a hodnotu ľudskej osobnosti, v rovnaké práva mužov a žien a že sa rozhodol podporovať sociálny pokrok a vytvoriť lepšie životné podmienky za vačšej slobody, že členské štáty prevzaly závazok zaistiť v spolupráci s Organizáciou Spojeých národov všeobecné uznávanie a zachovávanie ľudských práv a základýých slobod a že rovnaké chápanie týchto práv a slobod má nesmierny význam pre dokonalé

 

+ +

Spanish (Español)

+

Considerando que la libertad, la justicia y la paz en el mundo tienen por base el reconocimiento de la dignidad intrínseca y de los derechos iguales e inalienables de todos los miembros de la familia humana, Considerando que el desconocimiento y el menosprecio de los derechos humanos han originado actos de barbarie ultrajantes para la conciencia de la humanidad; y que se ha proclamado, como la aspiración más elevada del hombre, el advenimiento de un mundo en que los seres humanos, liberados del temor y de la miseria, disfruten de la libertad de palabra y de la libertad de creencias, Considerando esencial que los derechos humanos sean protegidos por un régimen de Derecho, a fin de que el hombre no se vea compelido al supremo recurso de la rebelión contra la tiranía y la opresión, Considerando también esencial promover el desarrollo de relaciones amistosas entre las naciones, Considerando que los pueblos de las Naciones Unidas han reafirmado en la Carta su fe en los derechos fundamentales del hombre, en la dignidad y el valor de la persona humana y en la igualdad de derechos de hombres y mujeres; y se han

 

+ +

Swedish (Svenska)

+

Enär erkännandet av det inneboende värdet hos alla medlemmar av människosläktet och av deras lika och oförytterliga rättigheter är grundvalen för frihet, rättvisa och fred i världen, enär ringaktning och förakt för de mänskliga rättigheterna lett till barbariska gärningar, som upprört mänsklighetens samvete, och enär skapandet av en värld, där människorna åtnjuta yttrandefrihet, trosfrihet samt frihet från fruktan och nöd, kungjorts som folkens högsta strävan, enär det är väsentligt för att icke människan skall tvingas att som en sista utväg tillgripa uppror mot tyranni och förtryck, att de mänskliga rättigheterna skyddas genom lagens överhöghet, enär det är väsentligt att främja utvecklandet av vänskapliga förbindelser mellan nationerna, enär Förenta Nationernas folk i stadgan ånyo uttryckt sin tro på de grundläggande mänskliga rättigheterna, den enskilda människans värdighet och värde samt männens och kvinnornas lika rättigheter, ävensom beslutat främja socialt framåtskridande och bättre levnadsvillkor under större frihet,

 

+ +

Turkish (Türkçe)

+

İnsanlık ailesinin bütün üyelerinde bulunan haysiyetin ve bunların eşit ve devir kabul etmez haklarının tanınması hususunun, hürriyetin, adaletin ve dünya barışının temeli olmasına, ınsan haklarının tanınmaması ve hor görülmesinin insanlık vicdanını isyana sevkeden vahşiliklere sebep olmuş bulunmasına, dehşetten ve yoksulluktan kurtulmuş insanların, içinde söz ve inanma hürriyetlerine sahip olacakları bir dünyanın kurulması en yüksek amaçları oralak ilan edilmiş bulunmasına, ınsanin zulüm ve baskıya karşı son çare olarak ayaklanmaya mecbur kalmaması için insan haklarının bir hukuk rejimi ile korunmasının esaslı bir zaruret olmasına, uluslararasında dostça ilişkiler geliştirilmesini teşvik etmenin esaslı bir zaruret olmasına, birleşmiş Milletler halklarının, Antlaşmada, insanın ana haklarına, insan şahsının haysiyet ve değerine, erkek ve kadınların eşitliğine olan imanlarını bir kere daha ilan etmiş olmalarına ve sosyal ilerlemeyi kolaylaştırmaya, daha geniş bir hürriyet içerisinde daha iyi hayat şartları kurmaya karar verdiklerini beyan etmiş bulunmalarına, üye devletlerin, birleşmiş Milletler Teşkilatı ile işbirliği ederek insan

 

+ +

Welsh (Cymraeg)

+

Gan mai cydnabod urddas cynhenid a hawliau cydradd a phriod holl aelodau’r teulu dynol yw sylfaen rhyddid, cyfiawnder a heddwch yn y byd, gan i anwybyddu a dirmygu hawliau dynol arwain at weithredoedd barbaraidd a dreisiodd gydwybod dynolryw, a bod dyfodiad byd lle y gall pob unigolyn fwynhau rhyddid i siarad a chredu a rhyddid rhag ofn ac angau wedi ei gyhoeddi yn ddyhead uchaf y bobl gyffredin, gan fod yn rhaid amddiffyn hawliau dynol a rheolaeth cyfraith, os nad yw pob unigolyn dan orfod yn y pendraw i wrthryfela yn erbyn gormes a thrais, gan fod yn rhaid hyrwyddo cysylltiadau cyfeillgar rhwng Cenhedloedd, gan fod pobloedd y Cenhedloedd Unedig yn y Siarter wedi ail ddatgan ffydd mewn hawliau sylfaenol yr unigolyn, mewn urddas a gwerth y person dynol ac mewn hawliau cydradd gŵr a gwragedd, ac wedi penderfynu hyrwyddo cynnydd cymdeithasol a safonau byw gwell mewn rhyddid helaethach, gan fod y Gwladwriaethau sy’n Aelodau wedi ymrwymo, mewn cydweithrediad â’r Cenhedloedd Unedig, i sicrhau hyrwyddo parch cyffredinol i hawliau dynol a’r rhyddfreintiau sylfaenol,

 

+ +

Vietnamese

+

Thần đồng Lê Quý Đôn làm bài thơ về Rắn ượng Lê Quý Đôn tại Trường THCS Lê Quý Đôn, Tp Hải Dương. Ảnh Bảo Ngọc Theo sử sách ghi lại, Lê Quý Đôn (1726 - 1784) thuở nhỏ tên là Lê Danh Phương, tự Doãn Hậu, hiệu Quế Đường; làm quan thời Lê trung hưng, là nhà thơ, và là "bác học lớn của Việt Nam trong thời phong kiến". Ngay từ nhỏ đã nổi tiếng là thần đồng, trở thành giai thoại và truyền thuyết về trí mẫn tiệp và óc thông minh, xuất chúng của ông. Theo giai thoại ở vùng Duyên Hà (Thái Bình), quê hương Lê Danh Phương có rất nhiều ao rộng, hồ sâu. Lê Danh Phương thường cùng bọn trẻ trong làng xuống ao trước cổng làng để tắm. Tuổi thơ tinh nghịch đang say sưa với trò nhảy trội, cậu nào cũng mình trần như nhộng, đứng xếp hàng ở bờ ao nghe "hiệu lệnh", tất cả nhảy tùm xuống nước, lặn ngụp thỏa thích rồi lên bờ xếp hàng, cứ thế nhảy trội cuốn hút bọn trẻ trong làng. Một hôm giữa trưa hè nóng bức, Tiến sĩ Vũ Công Trấn đến thăm Tiến sĩ Lê Phú Thứ là người bạn cùng đỗ Tiến sĩ khoa Giáp Thìn 1724 (sau đổi là Lê Trọng Thứ), Lê Danh Phương cùng bọn trẻ đang chơi trò nhảy trội thì có viên quan đi qua, tất cả bọn trẻ không có áo quần sợ quá nhảy tùm xuống ao lặn ngụp. Riêng Lê Danh Phương vẫn đứng trên bờ, không hề thẹn thùng. Cậu bé kháu khỉnh này hai tay chắp ra đằng sau, mắt đau đáu nhìn quan Thượng thư tinh nghịch. Quan Thượng thư thấy Lê Danh Phương đứng đó liền hỏi thăm đường…

 

+ +
+ +
diff --git a/content/font_testing/includes/latin/kerning.htmlpart b/content/font_testing/includes/latin/kerning.htmlpart new file mode 100644 index 0000000..e75597f --- /dev/null +++ b/content/font_testing/includes/latin/kerning.htmlpart @@ -0,0 +1,127 @@ +
+

22px

+

+ AABACADAEAFAGAHAIAJAKALAMANAOAPAQARASATAUAVAWAXAYAZA
+ BABBCBDBEBFBGBHBIBJBKBLBMBNBOBPBQBRBSBTBUBVBWBXBYBZB
+ CACBCCDCECFCGCHCICJCKCLCMCNCOCPCQCRCSCTCUCVCWCXCYCZC
+ DADBDCDDEDFDGDHDIDJDKDLDMDNDODPDQDRDSDTDUDVDWDXDYDZD
+ EAEBECEDEEFEGEHEIEJEKELEMENEOEPEQERESETEUEVEWEXEYEZE
+ FAFBFCFDFEFFGFHFIFJFKFLFMFNFOFPFQFRFSFTFUFVFWFXFYFZF
+ GAGBGCGDGEGFGGHGIGJGKGLGMGNGOGPGQGRGSGTGUGVGWGXGYGZG
+ HAHBHCHDHEHFHGHHIHJHKHLHMHNHOHPHQHRHSHTHUHVHWHXHYHZH
+ IAIBICIDIEIFIGIHIIJIKILIMINIOIPIQIRISITIUIVIWIXIYIZI
+ JAJBJCJDJEJFJGJHJIJJKJLJMJNJOJPJRJSJTJUJVJWJXJYJZJ
+ KAKBKCKDKEKFKGKHKIKJKKLKMKNKOKPKQKRKSKTKUKVKWKXKYKZK
+ LALBLCLDLELFLGLHLILJLKLLMLNLOLPLQLRLSLTLULVLWLXLYLZL
+ MAMBMCMDMEMFMGMHMIMJMKMLMMNMOMPMQMRMSMTMUMVMWMXMYMZM
+ NANBNCNDNENFNGNHNINJNKNLNMNNONPNQNRNSNTNUNVNWNXNYNZN
+ OAOBOCODOEOFOGOHOIOJOKOLOMONOOPOQOROSOTOUOVOWOXOYOZO
+ PAPBPCPDPEPFPGPHPIPJPKPLPMPNPOPPQPRPSPTPUPVPWPXPYPZP
+ QAQBQCQDQEQFQGQHQIQJQKQLQMQNQOQPQQRQSQTQUQVQWQXQYQZQ
+ RARBRCRDRERFRGRHRIRJRKRLRMRNRORPRQRRSRTRURVRWRXRYRZR
+ SASBSCSDSESFSGSHSISJSKSLSMSNSOSPSQSRSSTSUSVSWSXSYSZS
+ TATBTCTDTETFTGTHTITJTKTLTMTNTOTPTQTRTSTTUTVTWTXTYTZT
+ UAUBUCUDUEUFUGUHUIUJUKULUMUNUOUPUQURUSUTUUVUWUXUYUZU
+ VAVBVCVDVEVFVGVHVIVJVKVLVMVNVOVPVQVRVSVTVUVVWVXVYVZV
+ WAWBWCWDWEWFWGWHWIWJWKWLWMWNWOWPWQWRWSWTWUWVWWXWYWZW
+ XAXBXCXDXEXFXGXHXIXJXKXLXMXNXOXPXQXRXSXTXUXVXWXXYXZX
+ YAYBYCYDYEYFYGYHYIYJYKYLYMYNYOYPYQYRYSYTYUYVYWYYZY
+ ZAZBZCZDZEZFZGZHZIZJZKZLZMZNZOZPZQZRZSZTZUZVZWZXZYZZ
+
+ aabacadaeafagahaiajakalamanaoapaqarasatauavawaxayaza
+ babbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzb
+ cacbccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczc
+ dadbdcddedfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzd
+ eaebecedeefegeheiejekelemeneoepeqereseteuevewexeyeze
+ fafbfcfdfeffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzf
+ gagbgcgdgegfgghgigjgkglgmgngogpgqgrgsgtgugvgwgxgygzg
+ hahbhchdhehfhghhihjhkhlhmhnhohphqhrhshthuhvhwhxhyhzh
+ iaibicidieifigihiijikiliminioipiqirisitiuiviwixiyizi
+ jajbjcjdjejfjgjhjijjkjljmjnjojpjrjsjtjujvjwjxjyjzj
+ kakbkckdkekfkgkhkikjkklkmknkokpkqkrksktkukvkwkxkykzk
+ lalblcldlelflglhliljlkllmlnlolplqlrlsltlulvlwlxlylzl
+ mambmcmdmemfmgmhmimjmkmlmmnmompmqmrmsmtmumvmwmxmymzm
+ nanbncndnenfngnhninjnknlnmnnonpnqnrnsntnunvnwnxnynzn
+ oaobocodoeofogohoiojokolomonoopoqorosotouovowoxoyozo
+ papbpcpdpepfpgphpipjpkplpmpnpoppqprpsptpupvpwpxpypzp
+ qaqbqcqdqeqfqgqhqiqjqkqlqmqnqoqpqqrqsqtquqvqwqxqyqzq
+ rarbrcrdrerfrgrhrirjrkrlrmrnrorprqrrsrtrurvrwrxryrzr
+ sasbscsdsesfsgshsisjskslsmsnsospsqsrsstsusvswsxsyszs
+ tatbtctdtetftgthtitjtktltmtntotptqtrtsttutvtwtxtytzt
+ uaubucudueufuguhuiujukulumunuoupuqurusutuuvuwuxuyuzu
+ vavbvcvdvevfvgvhvivjvkvlvmvnvovpvqvrvsvtvuvvwvxvyvzv
+ wawbwcwdwewfwgwhwiwjwkwlwmwnwowpwqwrwswtwuwvwwxwywzw
+ xaxbxcxdxexfxgxhxixjxkxlxmxnxoxpxqxrxsxtxuxvxwxxyxzx
+ yaybycydyeyfygyhyiyjykylymynyoypyqyrysytyuyvywyyzy
+ zazbzczdzezfzgzhzizjzkzlzmznzozpzqzrzsztzuzvzwzxzyzz
+
+ Aar Abo Act Adj Aer Aft Aga Ahe Aie Aji Ake Alm Amo Ano Aoa App Aqu Art Ass Att Aug Ave Awa Axe Aye Azo Bal Bbn Bcc Bdj Ber Bfd Bga Bhu Bie Bji Bkl Bli Bmo Bni Boa Bpi Bqu Brt Bss Btl But Bve Bwa Bxl Bye Bzo Cal Cbn Ccn Cdj Cer Cfi Cga Che Cie Cjn Ckl Cle Cmo Cnl Coa Cpl Cqu Crl Css Ctl Cul Cvl Cwl Cxl Cyi Czo Dal Dbn Dci Ddj Der Dfl Dga Dhr Die Dji Dkl Dli Dmo Dnu Don Dpi Dqu Dri Dsl Dtl Dul Dvl Dwl Dxl Dya Dzn Ear Ebe Ech Edw Een Efo Ega Ehr Eit Ejo Ekn Eld Emp Ens Eob Epa Equ Ero Est Eth Euc Eva Ewa Exe Eyo Eze Fal Fbo Fci Fdj Fer Ffu Fgn Fhi Fil Fjo Fkl Fli Fmi Fnl Fol Fpi Fqu Fra Fst Fto Ful Fvl Fwl Fxi Fyi Fzi Gal Gbo Gch Gdj Ger Gfl Ggl Ghi Gil Gjl Gke Gli Gmo Gnl Gol Gpi Gqu Gra Gst Gto Gut Gve Gwl Gxi Gyn Gzn Har Hbo Hct Hdj Her Hfl Hga Hhe Hie Hji Hke Hlm Hmo Hno Hon Hpl Hqu Hrt Hss Htt Hue Hve Hwa Hxe Hyu Hzi Ian Ibo Ict Idj Ier Ift Iga Ihe Iie Ijo Ike Ilm Imo Ino Ion Ipl Iqu Irt Iss Ita Iut Ive Iwa Ixe Iyo Izo Jap Jbo Jct Jdj Jer Jfn Jgu Jhe Jie Jjl Jkl Jlm Jmo Jno Jon Jpl Jqu Jrt Jss Jtt Jut Jve Jwa Jxe Jyn Jzt Kan Kbo Kci Kdj Ker Kfn Kga Khe Kie Kjl Kkn Klm Kmo Kno Kon Kpl Kqu Krt Kss Kti Kui Kve Kwa Kxe Kye Kzo Lam Lbo Lct Ldj Len Lft Lga Lhe Lie Lju Lke Llm Lmo Lno Lon Lpl Lqu Lrt Lss Ltt Luc Lve Lwa Lxe Lye Lzt Mar Mbu Mct Mdj Mer Mfl Mga Mhe Mie Mji Mke Mlf Mmi Mnu Mon Mpl Mqu Mrt Mss Mtt Mut Mvl Mwa Mxe Myu Mzi Nam Nbu Nct Ndj Nel Nfl Nga Nhi Nie Njn Nke Nlo Nmi Nnu Non Npr Nqu Nrt Nst Ntu Nul Nvd Nwa Nxe Nyi Nzu Oan Obu Oct Odj Oer Ofa Oga Ohe Oie Oja Oke Olf Omi Onu Oon Opl Oqu Ort Oss Ott Out Ovl Owa Oxe Oye Ozo Par Pbl Pct Pdj Per Pfe Pgs Phi Pie Pji Pki Pla Pml Pnu Pon Ppl Pqu Prt Psa Pts Pul Pvc Pwi Pxl Pyn Pzl Qal Qbo Qct Qdj Qer Qfi Qga Qhe Qie Qji Qke Qlm Qmo Qno Qoa Qpp Qqu Qrt Qss Qtt Qui Qve Qwa Qxe Qyo Qzo Rad Rbi Rct Rdj Ren Rfe Rgs Rha Ria Rji Rkl Rli Rms Rni Roa Rpi Rqu Rrt Rsi Rtd Rut Rvi Rwl Rxi Ryn Rzi Sar Sbo Sct Sdl Ser Sfo Sgi She Sie Sja Ski Slo Smi Sno Sol Spe Squ Srt Sst Stt Sut Sve Swa Sxe Syl Szo Tar Tba Tcm Tdi Ter Tfl Tgi The Tie Tji Tke Tlm Tmo Tno Tol Tpi Tqu Trt Tsi Tti Tut Tvl Twl Txl Tyl Tzo Ual Ubi Uct Udj Uer Ufc Uga Uhi Uie Uji Uke Ulm Umo Uno Uol Upp Uqu Urt Uss Utl Uui Uvl Uwl Uxe Uye Uzo Val Vbo Vct Vdj Ver Vft Vga Vhe Vie Vjl Vki Vlm Vmo Vno Vol Vpi Vqu Vrl Vsi Vtt Vut Vvl Vwl Vxl Vyl Vzi Wal Wbo Wcl Wdj Wer Wfi Wga Whe Wie Wjl Wke Wlm Wmo Wno Wol Wpi Wqu Wrl Wsi Wtt Wut Wvl Wwl Wxl Wya Wzl Xal Xbo Xce Xdj Xer Xft Xga Xhe Xie Xjl Xki Xlm Xmo Xno Xol Xpi Xqu Xrl Xsi Xtt Xut Xvl Xwl Xxl Xye Xzi Yal Ybo Yci Ydj Yer Yfl Yga Yhe Yie Yjo Ykl Yli Ymo Yno Yol Ypi Yqu Yrl Ysi Ytt Yut Yvl Ywl Yxl Yyl Yzi Zan Zbr Zco Zdj Zer Zfl Zga Zhe Zie Zji Zke Zlm Zmo Zno Zol Zpi Zqu Zro Zsn Zti Zut Zvl Zwl Zxl Zyl Zzl
+
+ 01020304050607080900
+ 91929394959697989909
+ 81828384858687889808
+ 71727374757677879707
+ 61626364656676869606
+ 51525354556575859505
+ 41424344546474849404
+ 31323343536373839303
+ 21223242526272829202
+ 11213141516171819101
+
+ .1.2.3.4.5.6.7.8.9.0.
+ ,1,2,3,4,5,6,7,8,9,0,
+ '1'2'3'4'5'6'7'8'9'0'
+ -1-2-3-4-5-6-7-8-9-0-
+ –1–2–3–4–5–6–7–8–9–0–
+
+ -a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-
+ –a–b–c–d–e–f–g–h–i–j–k–l–m–n–o–p–q–r–s–t–u–v–w–x–y–z–
+ —a—b—c—d—e—f—g—h—i—j—k—l—m—n—o—p—q—r—s—t—u—v—w—x—y—z—
+ -A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X-Y-Z-
+ –A–B–C–D–E–F–G–H–I–J–K–L–M–N–O–P–Q–R–S–T–U–V–W–X–Y–Z–
+ —A—B—C—D—E—F—G—H—I—J—K—L—M—N—O—P—Q—R—S—T—U—V—W—X—Y—Z—
+
+ .a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.
+ ,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,
+ .A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.
+ ,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,
+ a; b; c; d; e; f; g; h; i; j; k; l; m; n; o; p; q; r; s; t; u; v; w; x; y; z;
+ a: b: c: d: e: f: g: h: i: j: k: l: m: n: o: p: q: r: s: t: u: v: w: x: y: z:
+ A; B; C; D; E; F; G; H; I; J; K; L; M; N; O; P; Q; R; S; T; U; V; W; X; Y; Z;
+ A: B: C: D: E: F: G: H: I: J: K: L: M: N: O: P: Q: R: S: T: U: V: W: X: Y: Z:
+
+ //a//b//c//d//e//f//g//h//i//j//k//l//m//n//o//p//q//r//s//t//u//v//w//y//z//
+ //A//B//C//D//E//F//G//H//I//J//K//L//M//N//O//P//Q//R//S//T//U//V//W//X//Y//Z//
+
+ ¿A? ¿B? ¿C? ¿D? ¿E? ¿F? ¿G? ¿H? ¿I? ¿J? ¿K? ¿L? ¿M? ¿N? ¿O? ¿P? ¿Q? ¿R? ¿S? ¿T? ¿U? ¿V? ¿W? ¿X? ¿Y? ¿Z?
+ ¿a? ¿b? ¿c? ¿d? ¿e? ¿f? ¿g? ¿h? ¿i? ¿j? ¿k? ¿l? ¿m? ¿n? ¿o? ¿p? ¿q? ¿r? ¿s? ¿t? ¿u? ¿v? ¿w? ¿x? ¿y? ¿z?
+ ¡a! ¡b! ¡c! ¡d! ¡e! ¡f! ¡g! ¡h! ¡i! ¡j! ¡k! ¡l! ¡m! ¡n! ¡o! ¡p! ¡q! ¡r! ¡s! ¡t! ¡u! ¡v! ¡w! ¡x! ¡y! ¡z!
+ ¡A! ¡B! ¡C! ¡D! ¡E! ¡F! ¡G! ¡H! ¡I! ¡J! ¡K! ¡L! ¡M! ¡N! ¡O! ¡P! ¡Q! ¡R! ¡S! ¡T! ¡U! ¡V! ¡W! ¡X! ¡Y! ¡Z!
+
+ “A” “B” “C” “D” “E” “F” “G” “H” “I” “J” “K” “L” “M” “N” “O” “P” “Q” “R” “S” “T” “U” “V” “W” “X” “Y” “Z”
+ “a” “b” “c” “d” “e” “f” “g” “h” “i” “j” “k” “l” “m” “n” “o” “p” “q” “r” “s” “t” “u” “v” “w” “x” “y” “z”
+
+ ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ ‘F’ ‘G’ ‘H’ ‘I’ ‘J’ ‘K’ ‘L’ ‘M’ ‘N’ ‘O’ ‘P’ ‘Q’ ‘R’ ‘S’ ‘T’ ‘U’ ‘V’ ‘W’ ‘X’ ‘Y’ ‘Z’
+ ‘a’ ‘b’ ‘c’ ‘d’ ‘e’ ‘f’ ‘g’ ‘h’ ‘i’ ‘j’ ‘k’ ‘l’ ‘m’ ‘n’ ‘o’ ‘p’ ‘q’ ‘r’ ‘s’ ‘t’ ‘u’ ‘v’ ‘w’ ‘x’ ‘y’ ‘z’
+
+ ’A’B’C’D’E’F’G’H’I’J’K’L’M’N’O’P’Q’R’S’T’U’V’W’X’Y’Z’
+ ’a’b’c’d’e’f’g’h’i’j’k’l’m’n’o’p’q’r’s’t’u’v’w’x’y’z’
+
+ 'A'B'C'D'E'F'G'H'I'J'K'L'M'N'O'P'Q'R'S'T'U'V'W'X'Y'Z'
+ 'a'b'c'd'e'f'g'h'i'j'k'l'm'n'o'p'q'r's't'u'v'w'x'y'z'
+
+ $12 $23 $34 $45 $56 $67 $78 $89 $90 $01
+ €12 €23 €34 €45 €56 €67 €78 €89 €90 €01
+ £12 £23 £34 £45 £56 £67 £78 £89 £90 £01
+ ¥12 ¥23 ¥34 ¥45 ¥56 ¥67 ¥78 ¥89 ¥90 ¥01
+ 12¢ 23¢ 34¢ 45¢ 56¢ 67¢ 78¢ 89¢ 90¢ 01¢
+
+ (a) (b) (c) (d) (e) (f) (g) (h) (i) (j) (k) (l) (m) (n) (o) (p) (q) (r) (s) (t) (u) (v) (w) (x) (y) (z) (A) (B) (C) (D) (E) (F) (G) (H) (I) (J) (K) (L) (M) (N) (O) (P) (Q) (R) (S) (T) (U) (V) (W) (X) (Y) (Z) {a} {b} {c} {d} {e} {f} {g} {h} {i} {j} {k} {l} {m} {n} {o} {p} {q} {r} {s} {t} {u} {v} {w} {x} {y} {z} {A} {B} {C} {D} {E} {F} {G} {H} {I} {J} {K} {L} {M} {N} {O} {P} {Q} {R} {S} {T} {U} {V} {W} {X} {Y} {Z} [a] [b] [c] [d] [e] [f] [g] [h] [i] [j] [k] [l] [m] [n] [o] [p] [q] [r] [s] [t] [u] [v] [w] [x] [y] [z] [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [K] [L] [M] [N] [O] [P] [Q] [R] [S] [T] [U] [V] [W] [X] [Y] [Z]
+
+ WOW.” ,’ ,” .’ ?” ?’ !” !’

+ ď! ď, ď. ď; ď? ďa ďh ďk ďl ďm ďo ďt ďu ďá ďž
+ Ľ. Ľa Ľu Ľú
+ ľ, ľ. ľ: ľ; ľa ľb ľg ľh ľk ľm ľn ľo ľs ľt ľu ľv ľú ľč ľň ľš
+ ť! ť" ť) ť, ť- ť. ť: ť; ť? ť` ťa ťc ťd ťj ťk ťm ťn ťo ťr ťs ťt ťu ťá ťž ť“
+

+
diff --git a/content/font_testing/includes/latin/layout.htmlpart b/content/font_testing/includes/latin/layout.htmlpart new file mode 100644 index 0000000..3eabd73 --- /dev/null +++ b/content/font_testing/includes/latin/layout.htmlpart @@ -0,0 +1,48 @@ +
+

Heading 60px, Subhead 24px, Body 16px

+

Doubts over insect-bite treatment

+ +

People should consider using a cold, wet cloth to treat insect bites instead of turning to over-the-counter remedies, experts say. Prof Michael Siva-Jothy, from Sheffield University's Department of Animal and Plant Sciences, recruited 29 brave volunteers to test the theory further, watching the bedbugs as they found a place to feed and removing them only as they were about to bite.

+

 

+ +
+

An investigation has concluded that there is little evidence that creams, painkillers and anti-inflammatories often used for bites actually work. In any case, said Drug and Therapeutics Bulletin researchers, the reactions got better by themselves in most cases. Midges, mosquitoes, flies, fleas and bed-bugs account for most bites. A variety of remedies are sold over the counter in pharmacies to relieve the itching, pain and swelling. + Other scientists have suggested that swapping thicker fur for clothes was a way of making insect bites and parasitic infestations less likely. + Prof Mark Pagel, an evolutionary biologist at the University of Reading, said that biting parasites remain a major cause of disease and death worldwide, making them a potentially enormous evolutionary pressure on early man.

+
+ +

 

+

 

+ +

Cold flannel ‘best’

+

 

+ +
+ +

Researchers from the journal reviewed a host of data and evidence published on insect-bite treatments. It concluded in many cases treatments for insect bites had not actually been tested for such purposes. It said medical help should clearly be sought if serious symptoms, such as infections or anaphylactic shock, developed. But it said for simple bites a flannel or cloth soaked in cold water often worked best - despite advice from official bodies, such as NHS Choices, suggesting treatments should be used. David Phizackerley, the deputy editor of the journal, said: “People are using these treatments so they should know there is no evidence they work. [Most] bites will get better on their own.” + Hungry bugs placed on shaved arms were more likely to try to feed compared with those on unshaved arms, the journal Biology Letters reported. Researchers say the hair slows down the bed bugs and warns the victim. Pest controllers say the UK is currently experiencing a steep rise in the number of bed bug infestations. Prof Michael Siva-Jothy, from Sheffield University's Department of Animal and Plant Sciences, recruited 29 brave volunteers to test the theory further, watching the bedbugs as they found a place to feed and removing them only as they were about to bite. + This tallies with other studies which look at how humans came to be relatively less hairy than apes.

+ +
    +
  1. Preface
  2. +
  3. Pre-Hot 100 era
  4. +
  5. Hot 100 era
  6. +
  7. Sources
  8. +
  9. See also
  10. +
+ +

He found that more layers of both longer visible hairs and finer, “vellus” hairs near the surface appeared to work as a deterrent to the insects, with the finer hairs also acting as an early warning system. + Continue reading the main story + “Start Quote + If you have a heavy coat of long thick hairs it is easier for parasites to hide” + Professor Siva-Jothy Sheffield University + Prof Siva-Jothy said: “Our findings show that more body hairs mean better detection of parasites - the hairs have nerves attached to them and provide us with the ability to detect displacement.” + He said they also slowed down the insect as it searched for a tasty spot to bite. + “The results have implications for understanding why we look the way we do, what selective forces might have driven us to look the way we do, and may even provide insight for better understanding of how to reduce biting insects’ impact on humans.” + However, even though men are naturally hairier than women, they do not appear to be bitten less often. + Professor Siva-Jothy suggested this pointed to an evolutionary battle between bed bugs and their prey, with the insects adapting to automatically head for relatively hairless bits of the body, such as wrists and ankles. + He added that extreme hairiness might also be more of a disadvantage than an advantage. + If you have a heavy coat of long thick hairs it is easier for parasites to hide, even if you can detect them. “Our proposal is that we retain the fine covering because it aids detection and if we lost all hair, even the relatively invisible fine hair, our detection ability goes right down.”

+
+ +
\ No newline at end of file diff --git a/content/font_testing/includes/latin/lettering.htmlpart b/content/font_testing/includes/latin/lettering.htmlpart new file mode 100644 index 0000000..04f1eba --- /dev/null +++ b/content/font_testing/includes/latin/lettering.htmlpart @@ -0,0 +1,19 @@ +
+ +

Lettering Sheet 72 points

+ +

A B C D E F G H
+ I J K L M N O P Q R
+ S T U V W X Y Z
+ a b c d e f g h i j k l m
+ n o p q r s t u v w x y z
+
+ 1 2 3 4 5 6 7 8 9 0
+
+ ( { [ . , ¡ ! ¿ ? * ] } )
+ # $ € £ % @ & ¶ § ¢ † ‡
+ ° _ : = ; + − - × ÷ ' ‘ ’ " “ ”
+ < > ≤ ± ≥ « ‹ © ® › »
+ ˜ ˙ ¯ ¨ ˝ ´ ` ˆ ˇ ˘ ˚ ¸ ˛

+ +
\ No newline at end of file diff --git a/content/font_testing/includes/latin/world-scripts.htmlpart b/content/font_testing/includes/latin/world-scripts.htmlpart new file mode 100644 index 0000000..2edafaf --- /dev/null +++ b/content/font_testing/includes/latin/world-scripts.htmlpart @@ -0,0 +1,111 @@ +
+ +

Cyrillic

+

Bulgarian

+

Ах чудна българска земьо, полюшквай цъфтящи жита.

 

+ +

Macedonian

+

Ѕидарски пејзаж: шугав билмез со чудење џвака ќофте и кељ на туѓ цех.

 

+ +

Mongolian

+

Щётканы фермд пийшин цувъя. Бөгж зогсч хэльюү.

 

+ +

Russian

+

Съешь же ещё этих мягких французских булок, да выпей чаю.

 

+ +

Ukrainian

+

Жебракують філософи при ґанку церкви в Гадячі, ще й шатро їхнє п'яне знаємо.

 

+ +

Devanagari

+

Hindi

+

दीवारबंद जयपुर ऐसी दुनिया है जहां लगभग हर दुकान का नाम हिन्दी में लिखा गया है। नामकरण की ऐसी तरतीब हिन्दुस्तान में कम दिखती है। दिल्ली में कॉमनवेल्थ गेम्स के दौरान कनॉट प्लेस और पहाड़गंज की नामपट्टिकाओं को एक समान करने का अभियान चला। पत्रकार लिख

 

+ +

Greek

+

Greek

+

Τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός

 

+ + + + + + +
+

Greek Polytonic

+

Πάτερ ἡμῶν ὁ ἐν τοῖς οὐρανοῖς· ἁγιασθήτω τὸ ὄνομά σου·
+ ἐλθέτω ἡ βασιλεία σου·
+ γενηθήτω τὸ θέλημά σου, ὡς ἐν οὐρανῷ, καὶ ἐπὶ τῆς γῆς·
+ τὸν ἄρτον ἡμῶν τὸν ἐπιούσιον δὸς ἡμῖν σήμερον·
+ καὶ ἄφες ἡμῖν τὰ ὀφειλήματα ἡμῶν,
+ ὡς καὶ ἡμεῖς ἀφίεμεν τοῖς ὀφειλέταις ἡμῶν·
+ καὶ μὴ εἰσενέγκῃς ἡμᾶς εἰς πειρασμόν, ἀλλὰ ῥῦσαι ἡμᾶς ἀπὸ τοῦ πονηροῦ.
+ Ἀμήν.

+
+

Greek Monotonic

+

Πάτερ ημών ο εν τοις ουρανοίς· αγιασθήτω το όνομά σου·
+ ελθέτω η βασιλεία σου·
+ γενηθήτω το θέλημά σου, ως εν ουρανώ, και επί της γης·
+ τον άρτον ημών τον επιούσιον δος ημίν σήμερον·
+ και άφες ημίν τα οφειλήματα ημών,
+ ως και ημείς αφίεμεν τοις οφειλέταις ημών·
+ και μη εισενέγκης ημάς εις πειρασμόν, αλλά ρύσαι ημάς από του πονηρού.
+ Αμήν.

+
+ +

Arabic

+

Arabic

+

صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت — يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ

 

+ +

Persian

+

بر اثر چنین تلقین و شستشوی مغزی جامعی، سطح و پایه‌ی ذهن و فهم و نظر بعضی اشخاص واژگونه و معکوس می‌شود.

 

+ +

Urdu

+

ر‌ضائی کو غلط اوڑھے بیٹھی ژوب کی قرۃ العین اور عظمٰی کے پاس گھر کے ذخیرے سے آناً فاناً ڈش میں ثابت جو، صراحی میں چائے اور پلیٹ میں زردہ آیا۔

 

+ +

Hebrew

+

כך התרסק נפץ על גוזל קטן, שדחף את צבי למים

 

+ +

Armenian

+

բել դղյակի ձախ ժամն օֆ ազգությանը ցպահանջ չճշտած վնաս էր և փառք

+

ԲԵԼ ԴՂՅԱԿԻ ՁԱԽ ԺԱՄՆ ՕՖ ԱԶԳՈՒԹՅԱՆԸ ՑՊԱՀԱՆՋ ՉՃՇՏԱԾ ՎՆԱՍ ԷՐ և ՓԱՌՔ

 

+ +

Georgian

+

ქართული ენა — ქართველების მშობლიური ენა, საქართველოს სახელმწიფო ენა (აფხაზეთის ავტონომიურ რესპუბლიკაში, მის პარალელურად, სახელმწიფო ენად აღიარებულია აფხაზური ენა). ქართულ ენაზე 5 მილიონზე მეტი ადამიანი ლაპარაკობს.

+ +

Thai

+

นายสังฆภัณฑ์ เฮงพิทักษ์ฝั่ง ผู้เฒ่าซึ่งมีอาชีพเป็นฅนขายฃวด ถูกตำรวจปฏิบัติการจับฟ้องศาล ฐานลักนาฬิกาคุณหญิงฉัตรชฎา ฌานสมาธิ

 

+ +

Bengali

+

বাংলা লিপি বাংলা, অসমীয়া, মণিপুরি ও সিলেটি ভাষায় ব্যবহৃত হয়৷ বাংলা লিপির গঠন তুলনামূলকভাবে কম আয়তাকার ও বেশী সর্পিল৷ বাংলা লিপিটি সিদ্ধং লিপি থেকে উদ্ভূত হয়েছে বলে মনে করা হয়৷ ১৭৭৮ সালে অক্ষরস্থাপক চার্ল্‌স্ উইলকিন্‌স্ লিপিটির আধুনিক রূপ সর্বপ্রথম নিয়মাবদ্ধ করেন৷ অসমীয়া ও অন্যান্য ভাষায় বাংলা লিপির যে সংস্করণগুলো ব্যবহৃত হয়, সেগুলোতে কিছু ছোটখাটো পার্থক্য রয়েছে৷ যেমন: (বাংলা র; অসমীয়া ৰ) এবং (অসমীয়া ৱ; কোন বাংলা প্রতিলিপি নেই)৷

+ +

Burmese

+

Myanmar

+

သီဟိုဠ်မှ ဉာဏ်ကြီးရှင်သည် အာယုဝဍ္ဎနဆေးညွှန်းစာကို ဇလွန်ဈေးဘေးဗာဒံပင်ထက် အဓိဋ္ဌာန်လျက် ဂဃနဏဖတ်ခဲ့သည်။

 

+ +

CJK

+

Japanese

+

いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす 色は匂へど 散りぬるを 我が世誰ぞ 常ならむ 有為の奥山 今日越えて 浅き夢見じ 酔ひもせず(ん)

 

+ +

Korean

+

키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다.

 

+ +

Ethiopic

+

ቃለ፡ በረከት፡ ዘሄኖክ፡ ዘከመ፡ ባረከ፡ ኅሩያነ፡ ወጻድቃነ፡ እለ፡ ሀለዉ፡ ይኩኑ፡ በዕለተ፡ ምንዳቤ፡ ለአሰስሎ፡ ኵሉ፡ እኩያን፡ ወረሲዓን።

+ +

Khmer

+

ខ្ញុំអាចញ៉ាំកញ្ចក់បាន ដោយគ្មានបញ្ហា

+ +

Lao

+

ຂອບໃຈຫຼາຍໆເດີ້ ໄຂປະຕູໃຫ້ແດ່

+

ໂຄງການ​ຫໍສະໝຸດ​ດິຈິ​ຕອລໜັງສື​ໃບ​ລານ​ລາວ ຂອງ​ຫໍສະໝຸດ​ແຫ່ງ​ຊາດ ນະ​ຄອນ​ຫລວງ​ວຽງ​ຈັນ ​ໄດ້​ຈັດ​ສະ​ເໜີ​ຮູບ​ພາບ​ດິຈິ​ຕອລ​ເອກະສານ​​ເກືອບ 12,000 ຕົ້ນ​ສະບັບ ຈາກ​ທົ່ວ​ປະ​ເທດ​ໂດຍ​ຜ່ານ​ອິນ​ເຕີ​ເນັດ ​ເພື່ອ​ຜູ້​ສົນ​ໃຈ​ສາມາດ​ໃຊ້​ສຶກສາ​ຄົ້ນຄວ້າ​ໄດ້​ໂດຍ​ສະ​ດວກ. ຄຼິກຫ້ອງ​ ‘ພາສາ​ລາວ’ ​ຢູ່​ທາງ​ເທິງ​ເພື່ອ​ເບິ່ງ​ເວັບ​ໄຊ​ພາສາ​ລາວ.

+ +

Tamil

+

தமிழ் அரிச்சுவடி என்பது தமிழ் மொழியில் உள்ள எழுத்துக்களின் வரிசை ஆகும். அரி என்னும் முன்னடை சிறு என்னும் பொருள் கொண்டது. இதனை தமிழ் அகரவரிசை, தமிழ் நெடுங்கணக்கு போன்ற சொற்களாலும் குறிப்பிடப்படுகிறது. தமிழில் 12 உயிரெழுத்துக்களும், 18 மெய்யெழுத்துக்களும், 216 உயிர்மெய் எழுத்துக்களும், ஓரு ஆய்த எழுத்துமாக மொத்தம் 247 எழுத்துக்கள் தமிழ் நெடுங்கணக்கில் உள்ளன. தற்காலத்தில் வழங்கும் கிரந்த எழுத்துக்கள் தமிழ் நெடுங்கணக்கைச் சேர்ந்ததல்ல.

+ +

Thaana

+

Missing Thaana sample text string

+ +

Tibetian

+

Dzongkha

+

ཨ་ཡིག་དཀར་མཛེས་ལས་འཁྲུངས་ཤེས་བློའི་གཏེར༎ ཕས་རྒོལ་ཝ་སྐྱེས་ཟིལ་གནོན་གདོང་ལྔ་བཞིན༎ ཆགས་ཐོགས་ཀུན་བྲལ་མཚུངས་མེད་འཇམ་དབྱངསམཐུས༎ མཧཱ་མཁས་པའི་གཙོ་བོ་ཉིད་འགྱུར་ཅིག།

 

+ +
diff --git a/examples/live/css/print-v9.css b/examples/live/css/print-v9.css new file mode 100644 index 0000000..7d88251 --- /dev/null +++ b/examples/live/css/print-v9.css @@ -0,0 +1,2 @@ +#top, #toggleotfeatures, #otfeatures, .tabNavigation, #footer, #formContainer,.dontprint {display:none;} +#fonts { position: relative; } \ No newline at end of file diff --git a/examples/live/css/rtl-v1.css b/examples/live/css/rtl-v1.css new file mode 100644 index 0000000..d9276e8 --- /dev/null +++ b/examples/live/css/rtl-v1.css @@ -0,0 +1,3 @@ +#custom { direction: rtl; } +ul.tabNavigation { margin-right: auto; } +#custom .tabs > div, #custom .tabs > div > div { margin-right: auto; } \ No newline at end of file diff --git a/examples/live/css/styles-v10.css b/examples/live/css/styles-v10.css new file mode 100644 index 0000000..53647ec --- /dev/null +++ b/examples/live/css/styles-v10.css @@ -0,0 +1,113 @@ +/* + + Notes: + A little wider than v9 + Used by Latin1 and Latin2 + + At some point, all other testing pages should be updated to use this css file only + +*/ + +/*---------------------------------------------------------------------------------------------------- + General Reset + ---------------------------------------------------------------------------------------------------*/ +body { background: white; color: black; margin: 0; padding: 0; } +section { display: block; float: left; margin: 0; padding: 0; width: 100%; } +h1, h2, h3, h4 { font-family: arial, sans-serif; font-weight: normal; } +ol { padding-left: 0px; list-style-position: inside; } + +/*---------------------------------------------------------------------------------------------------- + Top + ---------------------------------------------------------------------------------------------------*/ +#top { width: 960px; margin: 0 20px; padding: 0px; } +header { margin: 0; padding: 0; background: #cccccc;} +header h1 { margin: 0; padding: 40px 20px; } + +/* Font Selection */ +#fonts { width: 940px;margin: 0; padding: 0 10px; top: 0px; left: 20px; position: fixed; background: #F8F8F8; border-bottom: 1px solid #ccc; } +#fonts li { display: inline; list-style: none; margin: 0 16px 0 0; padding: 0; cursor: pointer; } +#fonts li.active { background: #CCCCCC; } + +/* OT Features Panel */ +#toggleotfeatures { float: left; width: 920px; margin: 0 20px; padding: 12px 20px; background-color: #bababa; font: normal 13px/13px "Lucida Grande","Lucida Sans Unicode", arial, sans-serif !important; } +#toggleotfeatures a { color: #fff; text-decoration:none; text-shadow: 1px 1px 2px black; } +#editions { float: right; } + +/* OT Features Menu */ +#otfeatures { float: left; width: 960px; margin: 0px 20px 10px; padding: 0px 0px 8px; background: #bababa; font: normal 13px/13px "Lucida Grande","Lucida Sans Unicode", arial, sans-serif !important; } +#otfeatures table td { padding: 4px 20px;} +#csscode { margin: 0; padding: 0; font: normal 10px/10px "Lucida Grande","Lucida Sans Unicode", arial, sans-serif; } + +/*----------------------------------------------------------------------------------------------------- + Content + ---------------------------------------------------------------------------------------------------*/ +.font-testing-page { margin: 0; padding: 0; } +.font-testing-page p { margin: 0; padding: 0; } +.font-testing-page p.sizelabel { font: normal 10px/10px "Lucida Grande","Lucida Sans Unicode", arial, sans-serif !important; color: #666; } + +/* Navigation */ +ul.tabNavigation { width: 960px; overflow: hidden; list-style: none; margin: 2px 20px; padding: 0; font: normal 15px/15px "Lucida Grande","Lucida Sans Unicode", arial, sans-serif !important; } +ul.tabNavigation li { float: left; padding: 0; margin: 0; } +ul.tabNavigation li a { display: block; padding: 7px 5px; margin: 2px 4px 2px 0px; color: #000; text-decoration: none; background-color: #ccc; } +ul.tabNavigation li a.selected, ul.tabNavigation li a:hover { color: #fff; background-color: #333; } +ul.tabNavigation li a:focus { outline: 0; } + +/* Default Styles for all tabs */ +div.tabs > div { padding: 20px; } + +/* Is this rule still used? If no longer used then it can be removed... */ +div.tabs > div h2 { margin-top: 0; } + +/* Rules for changing case*/ +.lowercase { + text-transform: lowercase; +} +.capitalized { + text-transform: capitalize; +} +.uppercase { + text-transform: uppercase; +} + +/*----------------------------------------------------------------------------------------------------- + Tab Specific Rules: + - If the rule is used in multiple tabs, put it here + - If the rule is only used in one specific tab and nowhere else, put it inline into the tab html + ---------------------------------------------------------------------------------------------------*/ + +/* Used in Text previews in multiple Tabs */ +.textsettingCol1 { width: 460px; float: left; } +.textsettingCol2 { width: 460px; float: right; } + +/* Used for the Unicode Tables and Unicode Lists */ +.bigslot { font-size: 50px; } + +/* Used for the Layout tabs */ +.multicolumn3 { + -moz-column-count: 3; + -moz-column-gap: 20px; + -webkit-column-count: 3; + -webkit-column-gap: 20px; + column-count: 3; + column-gap: 20px; +} + +/* 100 pixel ruler background */ +.ruler100pixels { + background: #ffffff url('../images/100pixels.png') repeat-x left top; +} + +/* These is used in the "Ruder" and "Ngrams" tab + * Maybe we can have a way to attach things like this to a specimen content + * without inlining on every element. Unfortumately + + +

Font SpecimenTools Example

+

We only show the very basics here, go to + mdlFontSpecimen + to see how these SpecimenTools should be used.

+ +

Size of Glyph-Set + +

+

Supported Languages + +

+
+

All Supported Languages

+

+
+ +
+ +

Porting: impallari/Font-Testing-Page

+ +
+ + + + +
+ + +
+
+ +
+

Choose a Font

+
+
+ +
+

Choose a File

+
+
+ +
+ +

Styles

+ + + +
+

+ +

+
+ +
+ + +

Test the Font

+
Default Features
+
+
Optional Features
+
+ +
Font size:
+
+ +
Letter spacing:
+
+ +
Line height:
+
+ +

+ TYPE HERE …
+ Web typography refers to the use of fonts on the World Wide Web. When + HTML was first created, font faces and styles were controlled exclusively + by the settings of each Web browser. There was no mechanism for individual + Web pages to control font display until Netscape introduced the <font> + tag in 1995, which was then standardized in the HTML 3.2 specification. + However, the font specified by the tag had to be installed on the user's + computer or a fallback font, such as a browser's default sans-serif or + monospace font, would be used. The first Cascading Style Sheets specification + was published in 1996 and provided the same capabilities. +

+ Source: Wikipedia + +
+ + + + diff --git a/examples/live/main.js b/examples/live/main.js new file mode 100644 index 0000000..f556810 --- /dev/null +++ b/examples/live/main.js @@ -0,0 +1,227 @@ +/* jshint esversion:6*/ +define([ + 'socket.io' + , 'specimenTools/services/LoadFiles' + , 'specimenTools/services/LoadFontsOpentypejs' + , 'specimenTools/initWidgets' + , 'specimenTools/services/PubSub' + , 'specimenTools/services/FontsLoadState' + , 'specimenTools/services/FontsData' + , 'specimenTools/services/WebfontProvider' + , 'specimenTools/services/RemoteLoader' + , 'specimenTools/widgets/GlyphTables' + , 'specimenTools/widgets/FamilyChooser' + , 'specimenTools/widgets/SimpleFileChooser' + , 'specimenTools/widgets/FontLister' + , 'specimenTools/widgets/GenericFontData' + , 'specimenTools/widgets/CurrentWebFont' + , 'specimenTools/widgets/TypeTester' + , 'specimenTools/widgets/PerFont' + , 'specimenTools/widgets/Diagram' + , 'specimenTools/widgets/DragScroll' + , 'specimenTools/widgets/SubSpecimenController' + , 'specimenTools/widgets/FontTestingPage/DataColumns' + , 'specimenTools/widgets/Mustache' +], function( + socketio + , LoadFiles + , LoadFontsOpentypejs + , initWidgets + , PubSub + , FontsLoadState + , FontsData + , WebFontProvider + , RemoteLoader + , GlyphTables + , FamilyChooser + , SimpleFileChooser + , FontLister + , GenericFontData + , CurrentWebFont + , TypeTester + , PerFont + , Diagram + , DragScroll + , SubSpecimenController + , FontTestingDataColumns + , Mustache +) { + "use strict"; + + /** + * A very basic initialization function without passing configuration + * with the factories array + */ + + function main(window) { + // This PubSub instance is the centrally connecting element between + // all modules. The order in which modules subscribe to PubSub + // channels is relevant in some cases. I.e. when a subscriber is + // dependant on the state of another module. + var pubsub = new PubSub() + , loadFiles = new LoadFiles(pubsub, {}, null) + , remoteLoader = new RemoteLoader() + , fontsLoadState = new FontsLoadState(pubsub) + , widgetDependencies + ; + + + // NOTE: handling current font and finding a replacement if it + // vanishes is still pretty fragile! + // It's important to subscribe this before `loadedFonts`/`fontsData` + // or whatever state is used to determine the `orderedIds` list. + // Because that way 'currentFont' is still present in the orderedIds + // and we can find its surrounding ids. + pubsub.subscribe('unloadFont', function(id) { + if(currentFont !== id) + return; + // orderedIds could be taken from fontData for better results, + // but then fontsData must subscribe *AFTER* this! + var // using fontsLoadState is not yielding particularly interesting results + // orderedIds = Array.from(fontsLoadState.getState().keys()) + // this is a proper order, but it depends on opentype.js: + orderedIds = fontsData.getFontIdsInFamilyOrder() + , [before, after] = _getNextToCurrent( + currentFont, orderedIds) + , newId = null + ; + + // pick first "after" second "before" + if(after !== null) + newId = after; + else if(before !== null) + newId = before; + + if(newId !== null) + pubsub.publish('activateFont', newId); + // if we don't find any id we don't activate anything. + }); + + var fontsData = new FontsData(pubsub, { + useLaxDetection: true, + + // passing in this object with a font's postscript name + // allows this name to be overwritten + overwrites: { + 'JosefinSans': 'Testname Josefin Sans' + } + }) + , webFontProvider = new WebFontProvider(window, pubsub, fontsData) + , socket = socketio('/') + ; + + // no use for the instance so far + /* loadFonts = */new LoadFontsOpentypejs(pubsub, { + // legacy support + eventNamePrefix: '' + }); + + + widgetDependencies = { + pubsub + , fontsLoadState + , fontsData + , webFontProvider + , remoteLoader + // , widgetsAPI + // => why not -> but using this via a service could be + // more unified interfaceCtrlTemplatesNode + , options: { + familyChooser: { + 'events.allFontsLoaded': false + } + , perFont: { + itemClass: 'per-font__item' + , bluePrintNodeClass: 'per-font__item-blueprint' + , fontDataClass: 'per-font__data' + , currentFontClass: 'per-font__current-font' + , 'events.allFontsLoaded': false + } + , subSpecimenController: { + injectionData: { + globals: {userAgent: navigator.userAgent} + } + } + , fontTestingDataColumns: {} + , mustache: {} + } + // this way we can also have a SubSpecimenController load + // widgets recursively. + , widgetFactories: [ + // [css-class of host element, Constructor(, further Constructor argument, ...)] + ['family-chooser', FamilyChooser, 'container', 'pubsub', 'fontsData', 'options.familyChooser'] + , ['simple-file-chooser' , SimpleFileChooser, 'container', 'pubsub'] + , ['glyph-table', GlyphTables, 'container', 'pubsub'] + , ['font-data', GenericFontData, 'container', 'pubsub', 'fontsData'] + , ['current-font', CurrentWebFont, 'container', 'pubsub', 'webFontProvider'] + , ['type-tester', TypeTester, 'container', 'pubsub', 'fontsData'] + , ['per-font', PerFont, 'container', 'pubsub', 'fontsData', 'webFontProvider', 'options.perFont'] + , ['diagram', Diagram, 'container', 'pubsub', 'fontsData', 'webFontProvider'] + , ['font-lister', FontLister, 'container', 'pubsub', 'fontsData'] + , ['drag-scroll', DragScroll, 'container'] + , ['sub-specimen_ctrl', SubSpecimenController, 'container', 'pubsub', 'fontsLoadState' + , 'remoteLoader', 'widgetDependencies', 'options.subSpecimenController'] + , ['font-testing-data', FontTestingDataColumns,'container', 'data.text' + , 'data.columns', 'options.fontTestingDataColumns'] + , ['mustache', Mustache, 'container', 'view', 'options.mustache'] + ] + }; + // self referential + widgetDependencies.widgetDependencies = widgetDependencies; + + /* let [instances, elements] = */ initWidgets(window.document + , widgetDependencies); + + function _getNextToCurrent(current, orderedIds) { + // if we have a state map that still contains the last current font + // this is an algorithm to find the id before and after ... + var before, after + , target = orderedIds.indexOf(current) + ; + before = after = null; + + if(target === -1) + before = after = orderedIds.length === 0 ? null : 0; + else { + before = target > 0 ? orderedIds[target-1] : null; + after = target+1 < orderedIds.length ? orderedIds[target+1] : null; + } + return [before, after]; + } + + var currentFont = null; + pubsub.subscribe('activateFont', function(id) { + currentFont = id; + }); + + pubsub.subscribe('loadFont', function(id) { + if(currentFont === null || currentFont === id) + // it's a reload, update all widgets + pubsub.publish('activateFont', id); + }); + + var spoof = 0; + socket.on('fs-watch', (eventName, id, fileInfo) => { + switch(eventName) { + case 'load': + // load initially or reload/update + fileInfo.url += `?spoof${spoof++}`; + loadFiles.oneFromUrl(id, fileInfo); + break; + case 'unload': + loadFiles.unload(id); + break; + } + }); + + socket.emit('subscribe', 'fs-watch', (fsStateEntries)=>{ + for(let [id, fileInfo] of fsStateEntries) + loadFiles.oneFromUrl(id, fileInfo); + }); + + // pubsub.subscribe(PubSub.$ALL, (channel, ...args)=>console.log(`PubSub.$ALL[${channel}]`, ...args)); + // pubsub.subscribe('activateFont', (...args)=>console.log(`PubSub[activateFont]`, ...args)); + } + + return main; +}); diff --git a/examples/simple/main.js b/examples/simple/main.js index 4d336af..fc25104 100644 --- a/examples/simple/main.js +++ b/examples/simple/main.js @@ -1,5 +1,7 @@ +/* jshint esversion:6 */ define([ - 'specimenTools/loadFonts' + 'specimenTools/services/LoadFiles' + , 'specimenTools/services/LoadFontsOpentypejs' , 'specimenTools/initDocumentWidgets' , 'specimenTools/services/PubSub' , 'specimenTools/services/FontsData' @@ -10,7 +12,8 @@ define([ , 'specimenTools/widgets/CurrentWebFont' , 'specimenTools/widgets/TypeTester' ], function( - loadFonts + LoadFiles + , LoadFontsOpentypejs , initDocumentWidgets , PubSub , FontsData @@ -36,17 +39,24 @@ define([ var pubsub = new PubSub() , factories , fontsData = new FontsData(pubsub, { - useLaxDetection: true, + useLaxDetection: true, // passing in this object with a font's postscript name // allows this name to be overwritten - overwrites: { - 'JosefinSans': 'Testname: Josefin Sans' - } + overwrites: { + 'JosefinSans': 'Testname Josefin Sans' + } }) , webFontProvider = new WebFontProvider(window, pubsub, fontsData) ; + // no use for the instance so far + /* loadFonts = */new LoadFontsOpentypejs(pubsub, { + // legacy support + eventNamePrefix: '' + }); + + factories = [ // [css-class of host element, Constructor(, further Constructor arguments, ...)] // All Constructors are given [dom-container, pubsub] as the first two arguments. @@ -59,11 +69,25 @@ define([ initDocumentWidgets(window.document, factories, pubsub); + pubsub.subscribe(PubSub.$ALL, (channel, ...args)=>console.log(`PubSub.$ALL[${channel}]`, ...args)); + pubsub.subscribe('allFontsLoaded', function() { pubsub.publish('activateFont', 0); }); - loadFonts.fromUrl(pubsub, fontFiles); + /* + var loadedFonts = new LoadProtocolState(pubsub, { + loadChannel: 'loadFont' + , unloadChannel: 'unloadFont' + , replayPrepareChannel: 'prepareFont' + // replayLoadChannel: defaults to loadChannel + , replayAllLoadedChannel: 'allFontsLoaded' + }); + + // now loadedFonts can be used to initate a sub-specimen: + loadedFonts.publish(subPubSub); + */ + LoadFiles.fromUrl(pubsub, fontFiles); } return main; diff --git a/lib/_BaseWidget.js b/lib/_BaseWidget.js index a044078..c650dbd 100644 --- a/lib/_BaseWidget.js +++ b/lib/_BaseWidget.js @@ -1,3 +1,4 @@ +/* jshint esversion:6 */ define([ './services/dom-tool' ], function( @@ -5,14 +6,23 @@ define([ ){ "use strict"; + const $DESTRUCTORS = Symbol('DESTRUCTORS'); + function _BaseWidget(options) { + // jshint validthis:true this._options = this._makeOptions(options); + + // If this is set,it's used by _p.destroy like an array + // as default implementation. Each item a callback. + this[$DESTRUCTORS] = null; + } _BaseWidget.defaultOptions = {}; var _p = _BaseWidget.prototype; _p.constructor = _BaseWidget; + _BaseWidget.$DESTRUCTORS = $DESTRUCTORS; _p._makeOptions = function(options) { // With Object.keys we won't get keys from the prototype @@ -35,5 +45,25 @@ define([ return pieces.join(''); }; + // is especially needed if e.g. this widget needs to unsubscribe from + // pubsub or so. I.e. wherever there are external references to this + // widget. + _p.destroy = function() { + if(this[$DESTRUCTORS]) { + for(let destructor of this[$DESTRUCTORS]) + destructor(); + } + // initial value is null and must be set to an array of destructors + // or to false. + else if (this[$DESTRUCTORS] === null) + // By default this raises, so we don't forget to implement + // destructors explicitly when needed! + // If no destructor is needed, a sub class could either + // re implement this method or an instance can define: + // this[_BaseWidget.$DESTRUCTORS] = false; + throw new Error(`destroy is not implemented in ${this.constructor.name}:\n ${this.constructor}`); + // else: pass + }; + return _BaseWidget; }); diff --git a/lib/bootstrap.js b/lib/bootstrap.js index 3f35f48..8e2d852 100644 --- a/lib/bootstrap.js +++ b/lib/bootstrap.js @@ -9,6 +9,7 @@ define([ require.config({ paths: { 'specimenTools': '.' + , 'socket.io': '/socket.io/socket.io' } }); diff --git a/lib/initDocumentWidgets.js b/lib/initDocumentWidgets.js index e940a14..ad71b5f 100644 --- a/lib/initDocumentWidgets.js +++ b/lib/initDocumentWidgets.js @@ -1,6 +1,8 @@ define([], function() { "use strict"; + console.warn('initDocumentWidgets is deprecated'); + /** * doc: a DOM document * factories: an array of arrays: diff --git a/lib/initWidgets.js b/lib/initWidgets.js new file mode 100644 index 0000000..4ac5962 --- /dev/null +++ b/lib/initWidgets.js @@ -0,0 +1,108 @@ +/* jshint esversion:6 */ +define([], function() { + "use strict"; + + function _filterNode(filterNodes, node) { + var i, l, filterNode; + for(i=0,l=filterNodes.length;i has a classList + // Can also be a DOM Document, which doesn't have a classList + // if it is an ELEMEMT_NODE, it can be a widget by itself. + if(host.nodeType === 1 && host.classList.contains(className)) + containersForClass.push(host); + if(host.querySelectorAll) + Array.prototype.push.apply(containersForClass, + host.querySelectorAll(`.${className}`)); + if(nodesFilter) + return containersForClass.filter(nodesFilter); + return containersForClass; + } + + function _getDependencies(argNames, ...dependencies) { + var args = []; + + entries: + for(let path of argNames) { + let parts = path.split('.'); + dependencies: + for(let depsDict of dependencies) { + // initially uses parts, but changes _parts + let _parts = parts; + while(true) { + let name; + [name, ..._parts] = _parts; + if(!(name in depsDict)) + // path doesn't lead anywhere + continue dependencies; + if(!_parts.length) { + args.push(depsDict[name]); + continue entries; // FOUND IT + } + // go deeper + depsDict = depsDict[name]; + } + } + throw new Error(`Can't resolve dependency "${path}"`); + } + return args; + } + + /** + * doc: a DOM Document or a DOM Element + * factories: an array of arrays: + * [ + * [ + * '.css-class-for-widget-container', + * WidgetConstructor, + * optional further WidgetConstructor_arguments + * , ... + * ] + * ] + * A WidgetConstructor will be called essentially like this: + * + * new WidgetConstructor(domContainer, + * pubsub, + * ..., further WidgetConstructor_arguments); + */ + function initWidgets(hosts, dependencies, filterNodes=null + , dependenciesForContainerFn=null) { + //i, l, className, containersForClass, Constructor + // , j, ll, container + var containers = [] + , instances = [] + , nodesFilter = filterNodes + ? _filterNode.bind(null, filterNodes) + : null + ; + if(!Array.isArray(hosts)) + hosts = [hosts]; + for(let host of hosts) { + for(let factory of dependencies.widgetFactories) { + let [className, Constructor, ...argNames] = factory + , containersForClass = _getContainers(host, className, nodesFilter); + for(let container of containersForClass) { + containers.push(container); + let containerDependencies = dependenciesForContainerFn + ? dependenciesForContainerFn(container) + : Object.create(null) + ; + let args = _getDependencies(argNames, {container} + , containerDependencies, dependencies); + instances.push(new Constructor(...args)); + } + } + } + return [instances, containers]; + } + + return initWidgets; +}); diff --git a/lib/loadFiles.js b/lib/loadFiles.js new file mode 100644 index 0000000..c050bfd --- /dev/null +++ b/lib/loadFiles.js @@ -0,0 +1,138 @@ +/* jshint esversion:6 */ +define([ +], function( +) { + "use strict"; + /*globals FileReader, XMLHttpRequest, console*/ + + console.warn('DEPRECATION: loadFiles.js is an outdated module, use' + + ' services/LoadFiles instead.'); + + /** + * Callback for when a file has been loaded + * + * @param id: id of the file loaded + * @param fileName + * @param err: null, error-object or string with error message + * @param arraybuffer + */ + function onLoadFile(id, fileName, err, arraybuffer) { + /* jshint validthis: true */ + + if(err) { + console.warn('Can\'t load file', id, fileName, ' with error:', err); + this.pubsub.publish('loadFileFail', id, fileName, err); + this.countFailed += 1; + } + else { + // This will also trigger to reload a file. + this.pubsub.publish('loadFile', id, fileName, arraybuffer); + this.countLoaded += 1; + } + + // FIXME: would be cool if we could avoid this event! + // All subscribers should implement ways to avoid requiring this + // event. Perhaps deprecate it. + // Also, the socket.io based files source won't trigger this + // at all, because `countAll` is expected to be null! + if(this.countLoaded + this.countFailed === this.countAll) + this.pubsub.publish('allFilesLoaded', this.countLoaded); + + } + + function loadFromUrl(fileInfo, callback) { + var request = new XMLHttpRequest() + , url = fileInfo.url + ; + request.open('get', url, true); + request.responseType = 'arraybuffer'; + request.onload = function() { + if (request.status !== 200) { + return callback('File could not be loaded: ' + request.statusText); + } + return callback(null, request.response); + }; + request.send(); + } + + function fileInputFileOnLoad(callback, loadEvent) { + /*jshint unused: vars, validthis:true*/ + callback(null, this.result); + } + function fileInputFileOnError(callback, loadEvent) { + /*jshint unused: vars, validthis:true*/ + callback(this.error); + } + function loadFromFileInput(file, callback) { + var reader = new FileReader(); + reader.onload = fileInputFileOnLoad.bind(reader, callback); + reader.onerror = fileInputFileOnError.bind(reader, callback); + reader.readAsArrayBuffer(file); + } + + function loadFilesFromFileInput(pubsub, fileInputFiles) { + _loadFiles(pubsub, fileInputFiles, loadFromFileInput); + } + loadFilesFromFileInput.needsPubSub = true; + + + function loadFilesFromUrl(pubsub, files) { + var i, l + , fileInfo = [] + ; + for(i=0,l=files.length;ithis._loadedFonts.destroy() + , this._pubsub.subscribe('activateFont', this._onActivateFont.bind(this)) + ]; + } + + const _p = FontsLoadState.prototype = Object.create(Parent.prototype); + FontsLoadState.constructor = FontsLoadState; + + FontsLoadState.defaultOptions = { + }; + + _p._onActivateFont = function(fontIndex) { + this._activeFont = fontIndex; + }; + + _p.publish = function(pubSub) { + this._loadedFonts.publish(pubSub); + if(this._activeFont) + pubSub.publish('activateFont', this._activeFont); + }; + + return FontsLoadState; +}); diff --git a/lib/services/LoadFiles.js b/lib/services/LoadFiles.js new file mode 100644 index 0000000..fd38098 --- /dev/null +++ b/lib/services/LoadFiles.js @@ -0,0 +1,144 @@ +/* jshint esversion:6 */ +define([ + 'specimenTools/_BaseWidget' +], function( + Parent +) { + "use strict"; + /*globals FileReader, XMLHttpRequest, console*/ + + function _loadFromAjaxUrl(fileInfo, callback) { + var request = new XMLHttpRequest() + , url = fileInfo.url + ; + request.open('get', url, true); + request.responseType = 'arraybuffer'; + request.onload = function() { + if (request.status !== 200) { + return callback('File could not be loaded: ' + request.statusText); + } + return callback(null, request.response); + }; + request.send(); + } + + function _loadFromFileInput(file, callback) { + var reader = new FileReader(); + reader.onload = (/*loadEvent*/)=>callback(null, reader.result); + reader.onerror = (/*loadEvent*/)=>callback(reader.error); + reader.readAsArrayBuffer(file); + } + + + function LoadFiles(pubsub, options, countAll=null) { + Parent.call(this, options); + + this._pubSub = pubsub; + this._countLoaded = 0; + this._countFailed = 0; + // if null: + // * there will be no allFilesLoaded event + // * loadFile can be a *reload* + // * unloadFile is possible/acceptable + // FIXME: unloadFile and loadFile which is a reload could be + // monitored in here and warned, if a countAll is given! + // That way we can be clear about expectations baked into the + // load protocols. + this._countAll = countAll; + this._loaded = new Set(); + } + + const _p = LoadFiles.prototype = Object.create(Parent.prototype); + LoadFiles.constructor = LoadFiles; + + LoadFiles.defaultOptions = {}; + + /** + * Callback for when a file has been loaded + * + * @param id: id of the file loaded + * @param fileName + * @param err: null, error-object or string with error message + * @param arraybuffer + */ + _p._onLoadFile = function(id, fileName, err, arraybuffer) { + + if(err) { + console.warn('Can\'t load file', id, fileName, ' with error:', err); + this._pubSub.publish('loadFileFail', id, fileName, err); + this._countFailed += 1; + } + else { + // This will also trigger to reload a file. + this._loaded.add(id); + this._pubSub.publish('loadFile', id, fileName, arraybuffer); + this._countLoaded += 1; + } + + // FIXME: would be cool if we could avoid this event! + // All subscribers should implement ways to avoid requiring this + // event. Perhaps deprecate it. + // Also, the socket.io based files source won't trigger this + // at all, because `countAll` is expected to be null! + if(this._countLoaded + this._countFailed === this._countAll) + this._pubSub.publish('allFilesLoaded', this._countLoaded); + }; + + _p._loadFile = function (loadFromSourceFunc, id, fileInfo) { + // jshint validthis:true + this._pubSub.publish('prepareFile', id, fileInfo.name, this._countAll); + var onload = this._onLoadFile.bind(this, id, fileInfo.name); + // The timeout thing is handy to slow down the load progress, + // if development is done on that part. + // setTimeout(function(fileInfo, onload) { + loadFromSourceFunc(fileInfo, onload); + // }.bind(null, fileInfo, onload), Math.random() * 5000); + }; + + _p.oneFromUrl = function(id, fileInfo) { + this._loadFile(_loadFromAjaxUrl, id, fileInfo); + }; + + _p.unload = function(id) { + if(!this._loaded.has(id)) + return; + this._loaded.delete(id); + this._pubSub.publish('unloadFile', id); + }; + + // a (meta) factory for LoadFiles + function _loadFilesFactory(pubsub, files, loadFromSourceFunc) { + var loadFiles = new LoadFiles(pubsub, {}, files.length); + for(let i=0,l=files.length;ia-b) ; - for(i=1,l=arguments.length;i{resolve=res; reject=rej;}) + ; + request.open('get', url, true); + request.responseType = responseType || 'text'; + request.onload = ()=>{ + if (request.status !== 200) + return reject('File could not be loaded: ' + request.statusText); + return resolve(request.response); + }; + request.send(); + return promise; + } + + const Source = (function(){ + function Source(parse) { + this._parse = parse; + } + + const _p = Source.prototype; + + _p.load = function() { + throw new Error('load is not implemented'); + }; + + return Source; + })(); + + const HTTPGetSource = (function(Parent) { + function HTTPGetSource(responseType, ...args) { + Parent.call(this, ...args); + this._responseType = responseType; + } + + const _p = HTTPGetSource.prototype = Object.create(Parent.prototype); + + _p.load = function(url, ...extraArgs) { + var promise = _loadFromAjaxUrl(url, this._responseType); + return this._parse + ? promise.then(result=>this._parse(result, ...extraArgs)) + : promise + ; + }; + + return HTTPGetSource; + })(Source); + + // straight from MDN + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze + function deepFreeze(object) { + + // Retrieve the property names defined on object + var propNames = Object.getOwnPropertyNames(object); + + // Freeze properties before freezing self + + for (let name of propNames) { + let value = object[name]; + + if(value && typeof value === "object") { + deepFreeze(value); + } + } + + return Object.freeze(object); + } + + function RemoteLoader(/* TODO: sources*/) { + this._sources = { + // simple http get: + 'HTTP-get-text': new HTTPGetSource('text') + , 'HTTP-get-fragment': new HTTPGetSource('text', domTool.createFragmentFromHTML) + , 'HTTP-get-markdown': new HTTPGetSource('text', domTool.createFragmentFromMarkdown) + , 'HTTP-get-json': new HTTPGetSource('json', (result, freeze=true)=>freeze?deepFreeze(result):result) + }; + } + + const _p = RemoteLoader.prototype; + _p.constructor = RemoteLoader; + + + /** + * contentAddress: "{sourceName}:{contentName}" + */ + _p.load = function(contentAddress, ...extraArgs) { + var separator = ':' + , sepIndex = contentAddress.indexOf(separator) + // In the case of no separator there's no contentName (''). + , sourceName = sepIndex >= 0 + ? contentAddress.slice(0, sepIndex) + : contentAddress + , contentName = sepIndex >= 0 + ? contentAddress.slice(sepIndex + separator.length) + : '' + , source = this._sources[sourceName] + ; + + + // TODO: could be cached, but may need a way to invalidate. + // also, if there's a way to invalidate it would be cool + // to have a way to automatically inform (subbscription) + // the user and reload. Would be a nice way to work on + // a specimen and have it reload on a change to its markup. + // But that wouldn't cover all cases. Reloading the CSS + // would be also nice via that mechanism. + // ALSO: LoadFiles/LoadFonts{Library} is VERY much related + // at that point. Need to find out how to separate the + // channels/purposes though. + // FIXME: always as a promise? It's much quicker to implement. + return Promise.resolve(source.load(contentName, ...extraArgs)); + }; + + return RemoteLoader; +}); diff --git a/lib/services/WebfontProvider.js b/lib/services/WebfontProvider.js index 75393f3..b8b5b9f 100644 --- a/lib/services/WebfontProvider.js +++ b/lib/services/WebfontProvider.js @@ -1,3 +1,4 @@ +/* jshint esversion:6 */ define([ 'specimenTools/_BaseWidget' ], function( @@ -5,6 +6,18 @@ define([ ) { "use strict"; + + // These are all used enable removing loaded fonts. + // For css-connected rules (oldschool, via a @font-face rule + // _url and _cssRule are stored, but it looks like that way + // of loading fonts is not needed anymore. + const _url = Symbol('url') + , _cssRule = Symbol('cssRule') + , _fontFace = Symbol('fontFace') + // used for a cache + , _props = Symbol('props') + ; + /** * WebFontProvider takes the original arraybuffer of the loaded fonts * and adds it as a Web-Font—i.e. as loaded with @font-face—to the @@ -14,12 +27,12 @@ define([ * are taken from the font directly, via the FontData service and * there via opentype.js. * - * The public method `setStyleOfElement(fontIndex, element)` - * sets the element.style so that the web font with fontIndex is + * The public method `setStyleOfElement(fontID, element)` + * sets the element.style so that the web font with fontID is * displayed. * - * The public method `getStyleProperties(fontIndex)` returns a string - * of CSS properties that would make the font with fontIndex being + * The public method `getStyleProperties(fontID)` returns a string + * of CSS properties that would make the font with fontID being * displayed. */ function WebFontProvider(window, pubsub, fontData, options) { @@ -27,9 +40,12 @@ define([ this._window = window; this._pubSub = pubsub; this._fontData = fontData; - this._pubSub.subscribe('loadFont', this._onLoadFont.bind(this)); - this._data = []; - this._blobs = []; + + this[Parent.$DESTROY]=[ + this._pubSub.subscribe('loadFont', this._onLoadFont.bind(this)) + , this._pubSub.subscribe('unloadFont', this._onUnloadFont.bind(this)) + ]; + this._data = {}; this.__stylesheet = null; } @@ -53,15 +69,15 @@ define([ } }); - _p._makeWebfont = function(fontIndex) { - var arrBuff = this._fontData.getOriginalArraybuffer(fontIndex) - , familyName = this._fontData.getCSSFamilyName(fontIndex) - , weight = this._fontData.getCSSWeight(fontIndex) - , style = this._fontData.getCSSStyle(fontIndex) + _p._makeWebfont = function(fontID) { + var arrBuff = this._fontData.getOriginalArraybuffer(fontID) + , familyName = this._fontData.getCSSFamilyName(fontID) + , weight = this._fontData.getCSSWeight(fontID) + , style = this._fontData.getCSSStyle(fontID) , fontface, url, blob, styleData ; - this._data[fontIndex] = styleData = Object.create(null); + this._data[fontID] = styleData = Object.create(null); styleData['font-style'] = style; styleData['font-weight'] = weight; styleData['font-family'] = familyName; @@ -77,53 +93,92 @@ define([ weight: weight , style: style }); - this._window.document.fonts.add( fontface ); + this._window.document.fonts.add(fontface); + styleData[_fontFace] = fontface; } else { - // oldschool, a bit bloated + // oldschool, a bit bloated, probably outdated + // https://www.w3.org/TR/css-font-loading-3/#css-connected + // to remove, the css @font-face rule must be removed blob = new this._window.Blob([arrBuff], { type: 'font/opentype' }); - this._blobs[fontIndex] = blob; url = this._window.URL.createObjectURL(blob); - this._styleSheet.insertRule([ + styleData[_url] = url; + let ruleIndex = this._styleSheet.insertRule([ '@font-face {' - , this.getStyleProperties(fontIndex) + , this.getStyleProperties(fontID) , 'src: url(' + url + ');' , '}' ].join(''), this._styleSheet.cssRules.length); + styleData[_cssRule] = this._styleSheet.cssRules[ruleIndex]; + } + }; + + _p._removeWebfont = function(fontID) { + + var styleData = this._data[fontID]; + if(!styleData) + return; + if('FontFace' in this._window) { + let fontface = styleData[_fontFace]; + this._window.document.fonts.delete(fontface); } + else { + // oldschool, a bit bloated, probably outdated + let cssRule = styleData[_cssRule]; + for(let ruleIndex=0,l=this._styleSheet.cssRules.length;ruleIndex) and the `contenteditable` attribute: + * trustedOrOptions = { + * ADD_TAGS: ['#comment'] + * , ADD_ATTR: ['contenteditable'] + * } + * For more info see: https://github.com/cure53/DOMPurify + */ + function createFragmentFromHTML(html, trustedOrOptions=false) { + if(trustedOrOptions === false || typeof trustedOrOptions === 'object') { + let purifyOptions = trustedOrOptions === false + ? undefined + : trustedOrOptions + ; + html = DOMPurify.sanitize(html, purifyOptions); + } + return document.createRange().createContextualFragment(html); + } + + function createFragment(contents, cloneChildNodes) { + var frag = document.createDocumentFragment(); + appendChildren(frag, contents, cloneChildNodes); + return frag; + } + + function createComment(text) { + return document.createComment(text); + } + + function isDOMElement(node) { + return node && node.nodeType && node.nodeType === 1; + } + + function replaceNode(newNode, oldNode) { + if(oldNode.parentNode) // replace has no effect if oldNode has no place + oldNode.parentNode.replaceChild(newNode, oldNode); + } + + function removeNode(node) { + if(node.parentNode) + node.parentNode.removeChild(node); + } + + function insertBefore(newElement, referenceElement) { + if(referenceElement.parentNode && newElement !== referenceElement) + referenceElement.parentNode.insertBefore(newElement + , referenceElement); + } + + function insertAfter(newElement, referenceElement) { + // there is no element.insertAfter() in the DOM + if(!referenceElement.nextSibling) + referenceElement.parentNode.appendChild(newElement); + else + insertBefore(newElement, referenceElement.nextSibling); + } + + function insert(element, position, child) { + switch(position) { + case 'append': + element.appendChild(child); + break; + case 'prepend': + if(element.firstChild) + insertBefore(child, element.firstChild); + else + element.appendChild(child); + break; + case 'before': + insertBefore(child, element); + break; + case 'after': + insertAfter(child, element); + break; + default: + throw new ValueError('Unknown position keyword "'+position+'".'); + } + } + + function insertElement(into, element, pos) { + var children = into.children || into.childNodes + , append = children.length + ; + if(pos === undefined || pos > append) + pos = append; + else if(pos < 0) { + pos = children.length + pos; + if(pos < 0) + pos = 0; + } + if(pos === append) + into.appendChild(element); + else + into.insertBefore(element, children[pos]); + } + + function getChildElementForSelector(element, selector, deep) { + + var elements = Array.prototype.slice + .call(element.querySelectorAll(selector)); + if(!deep) + // I don't know an easier way to only allow + // direct children. + elements = elements.filter(function(elem) { + return elem.parentNode === element;}); + return elements[0] || null; + } + + function* getMarkerComments(element, marker) { + var frames = [[element && element.childNodes, 0]] + , frame, nodelist, i, l, childNode + , markerTestFn = typeof marker === 'string' + ? trimmedText => trimmedText === marker + // expect it to be a function + : marker + ; + main: + while((frame = frames.pop()) !== undefined){ + nodelist = frame[0]; + for(i=frame[1],l=nodelist.length;i not found'); + } + + function clear(target, destroyEventName) { + while(target.lastChild) { + if(destroyEventName) + // children can listen for the event and cleanup if needed + // activatedElement.addEventListener('destroy', function (e) { //... }, false); + target.lastChild.dispatchEvent(new Event(destroyEventName)); + removeNode(target.lastChild); + } + } + + function validateChildEvent(event, stopElement, searchAttribute) { + var elem = event.target + , searchAttributes = [searchAttribute] + , i, l, results + ; + if(event.defaultPrevented) return; + + for(i=3,l=arguments.length;i append) - pos = append; - else if(pos < 0) { - pos = children.length + pos; - if(pos < 0) - pos = 0; - } - if(pos === append) - into.appendChild(element); - else - into.insertBefore(element, children[pos]); - } - return { - applyClasses: applyClasses - , insertElement: insertElement + createElement: createElement + , createChildElement: createChildElement + , createElementfromHTML: createElementfromHTML + , createElementfromMarkdown: createElementfromMarkdown + , createTextNode: createTextNode + , appendChildren: appendChildren + , appendHTML: appendHTML + , appendMarkdown: appendMarkdown + , createFragment: createFragment + , createComment: createComment + , createFragmentFromHTML: createFragmentFromHTML + , createFragmentFromMarkdown: createFragmentFromMarkdown + , isDOMElement: isDOMElement + , replaceNode: replaceNode + , removeNode: removeNode + , insert: insert + , insertAfter: insertAfter + , insertBefore: insertBefore + , insertElement:insertElement + , getChildElementForSelector: getChildElementForSelector + , getMarkerComment: getMarkerComment + , getMarkerComments: getMarkerComments + , insertAtMarkerComment: insertAtMarkerComment + , clear: clear + , validateChildEvent: validateChildEvent + , ValueError: ValueError + , applyClasses: applyClasses }; }); diff --git a/lib/services/svgDrawing/DiagramRenderer.js b/lib/services/svgDrawing/DiagramRenderer.js index cfc4962..4685934 100644 --- a/lib/services/svgDrawing/DiagramRenderer.js +++ b/lib/services/svgDrawing/DiagramRenderer.js @@ -78,7 +78,9 @@ define([ ; switch(type) { case('glyph'): - content = this._fontsData.getGlyphByName(fontIndex, instructions[1]); + // content = this._fontsData.getGlyphByName(fontIndex, instructions[1]); + content = this._fontsData.getGlyphByChar(fontIndex, instructions[1]); + if(!content) throw new Error('DiagramRenderer: can\'t find glyph ' + 'with name "'+instructions[1]+'"'); diff --git a/lib/setup.js b/lib/setup.js index 931ed89..f4654d2 100644 --- a/lib/setup.js +++ b/lib/setup.js @@ -6,6 +6,9 @@ define([ // baseUrl: 'lib' should be already set by the file that includes this file paths: { 'opentype': 'bower_components/opentype.js/dist/opentype' + , 'dompurify': 'bower_components/DOMPurify/dist/purify.min' + , 'marked': 'bower_components/marked/marked.min' + , 'mustache': 'bower_components/mustache.js/mustache' , 'Atem-CPS-whitelisting': 'bower_components/Atem-CPS-whitelisting/lib' , 'Atem-Errors': 'bower_components/Atem-Errors/lib' , 'Atem-Math-Tools': 'bower_components/Atem-Math-Tools/lib' diff --git a/lib/widgets/CurrentWebFont.js b/lib/widgets/CurrentWebFont.js index 43b1512..2d019fc 100644 --- a/lib/widgets/CurrentWebFont.js +++ b/lib/widgets/CurrentWebFont.js @@ -20,7 +20,10 @@ define([ this._container = container; this._webFontProvider = webFontProvider; this._pubSub = pubSub; - this._pubSub.subscribe('activateFont', this._onActivateFont.bind(this)); + + this[Parent.$DESTRUCTORS] = [ + this._pubSub.subscribe('activateFont', this._onActivateFont.bind(this)) + ]; } var _p = CurrentWebFont.prototype = Object.create(Parent.prototype); diff --git a/lib/widgets/Diagram.js b/lib/widgets/Diagram.js index 2246314..735f510 100644 --- a/lib/widgets/Diagram.js +++ b/lib/widgets/Diagram.js @@ -122,7 +122,7 @@ define([ , options = Object.create(null) , renderer ; - if(this._svg) + if(this._svg && this._svg.parentNode) this._container.removeChild(this._svg); if(typeof instructionSet === 'function') diff --git a/lib/widgets/DragScroll.js b/lib/widgets/DragScroll.js index e7a4ea5..ec0c985 100644 --- a/lib/widgets/DragScroll.js +++ b/lib/widgets/DragScroll.js @@ -5,10 +5,9 @@ define([ ) { "use strict"; - function DragScroll(container, pubSub, options) { + function DragScroll(container, options) { Parent.call(this, options); this._container = container; - this._pubSub = pubSub; this._container.addEventListener('mousedown', this._initDrag.bind(this)); this._container.addEventListener('touchstart', this._initDrag.bind(this)); diff --git a/lib/widgets/FamilyChooser.js b/lib/widgets/FamilyChooser.js index e13cd71..ef56d55 100644 --- a/lib/widgets/FamilyChooser.js +++ b/lib/widgets/FamilyChooser.js @@ -1,3 +1,4 @@ +/* jshint esversion:6 */ define([ 'specimenTools/_BaseWidget' ], function( @@ -37,11 +38,15 @@ define([ this._switchesContainer = this._container.ownerDocument.createElement('div'); this._container.appendChild(this._switchesContainer); - this._pubSub.subscribe('loadFont', this._onLoadFont.bind(this)); - this._pubSub.subscribe('allFontsLoaded', this._onAllFontsLoaded.bind(this)); + if(this._options['events.allFontsLoaded']) + this._pubSub.subscribe('allFontsLoaded', this._onAllFontsLoaded.bind(this)); + else { + this._pubSub.subscribe('loadFont', this._onLoadFont.bind(this)); + this._pubSub.subscribe('unloadFont', this._onUnloadFont.bind(this)); + } + this._pubSub.subscribe('activateFont', this._onActivateFont.bind(this)); - this._fonts = []; this._activeFont = null; this._familiesData = null; this._fontData = null; @@ -61,16 +66,14 @@ define([ } , weightButtonClasses: [] , weightButtonActiveClass: 'active' + // make it false to allow for unload/load/reload + , 'events.allFontsLoaded': true }; _p._otherStyle = function otherStyle(style) { return style === 'normal' ? 'italic' : 'normal'; }; - _p._onLoadFont = function (fontIndex, fontFileName, font) { - this._fonts[fontIndex] = font; - }; - _p._switchItalic = function(checkbox) { var fontData = this._fontData[this._activeFont] , fontId @@ -89,8 +92,9 @@ define([ _p._switchFont = function(familyIndex, weight) { // get Font Id ... - var currentStyle = this._activeFont !== null - ? this._fontData[this._activeFont].style + var fontData = this._activeFont && this._fontData[this._activeFont] + , currentStyle = fontData + ? fontData.style : 'normal' , styleDict = this._familiesData[familyIndex][1][weight] , fontId = currentStyle in styleDict @@ -136,7 +140,7 @@ define([ return weightButton; }; - // TODO!! + // TODO!! what? _p._makeFamilyElement = function(familyIndex, familyName, weightDict) { // default text-sort should suffice here var weights = Object.keys(weightDict).sort() @@ -182,8 +186,8 @@ define([ }; _p._getFontData = function(familiesData) { - var fontData = [] - , familyIndex, fontIndex, l, familyName, weightDict, weight + var fontData = {} + , familyIndex, fontId, l, familyName, weightDict, weight , styleDict, style, otherStyle ; @@ -193,11 +197,11 @@ define([ for(weight in weightDict) { styleDict = weightDict[weight]; for(style in styleDict) { - fontIndex = styleDict[style]; + fontId = styleDict[style]; otherStyle = styleDict[this._otherStyle(style)]; otherStyle = otherStyle !== undefined ? otherStyle : null; - fontData[fontIndex] = { + fontData[fontId] = { familyIndex: familyIndex , weight: weight , style: style @@ -210,32 +214,57 @@ define([ return fontData; }; - _p._onAllFontsLoaded = function(countAll) { + _p._onAllFontsLoaded = function(/*countAll*/) { /*jshint unused:vars*/ - var familiesData = this._fontsDataObject.getFamiliesData() - , familyElements = [] + var familiesData = this._familiesData = this._fontsDataObject.getFamiliesData() + , familyElements = this._familyElements = [] , doc = this._container.ownerDocument , i, l ; + this._fontData = this._getFontData(familiesData); + for(i=0,l=familiesData.length;i 0) - this._container.appendChild(doc.createElement('hr')); + this._switchesContainer.appendChild(doc.createElement('hr')); familyElements[i] = this._makeFamilyElement(i, familiesData[i][0] , familiesData[i][1]); // put all family elements into the FamilyController block - this._container.appendChild(familyElements[i].element); - + this._switchesContainer.appendChild(familyElements[i].element); } - this._familiesData = familiesData; - this._fontData = this._getFontData(familiesData); - this._familyElements = familyElements; }; - _p._activateFont = function(i) { + _p._updateFontsLoaded = function() { + // could be used on load, reload, unload and also allFontsLoaded! + + // TODO: keep active font selection. + + // It would be much nicer to have this just update changed elements. + for(let element of Array.from(this._switchesContainer.childNodes)) + element.parentNode.removeChild(element); + this._onAllFontsLoaded(); + // keep selection + if(this._activeFont) + this._onActivateFont(this._activeFont); + }; + + _p._onLoadFont = function (fontId, fontFileName, font) { + // jshint unused: vars + this._updateFontsLoaded(); + }; + + _p._onUnloadFont = function (fontId) { + // jshint unused: vars + + // TODO: could/should perhaps activate another font! BUT, there + // should be only one widgets that activates a new font on unload. + this._updateFontsLoaded(); + }; + + _p._activateFont = function(fontId) { // this will call this._onActivateFont - this._pubSub.publish('activateFont', i); + this._pubSub.publish('activateFont', fontId); }; _p._setWeightButton = function(weightButton, isActive) { @@ -253,10 +282,12 @@ define([ familyElement.classList[isActive ? 'add' : 'remove']('active'); }; - _p._onActivateFont = function(fontIndex) { + _p._onActivateFont = function(fontId) { // this should only change the view, not emit signals // make the button(s) enabled/disabled and active/inactive etc. - var fontData = this._fontData[fontIndex] + if(!this._fontData[fontId]) + return; + var fontData = this._fontData[fontId] , familyIndex = fontData.familyIndex, familyIdx, l // all families: check/uncheck italic switches , italicChecked = fontData.style === 'italic' @@ -283,7 +314,7 @@ define([ this._setWeightButton(weights[weight], weightActive); } } - this._activeFont = fontIndex; + this._activeFont = fontId; }; return FamilyChooser; diff --git a/lib/widgets/FontLister.js b/lib/widgets/FontLister.js index b89bc99..9120ebf 100644 --- a/lib/widgets/FontLister.js +++ b/lib/widgets/FontLister.js @@ -1,3 +1,4 @@ +/* jshint esversion:6 */ define([ 'specimenTools/_BaseWidget' ], function( @@ -22,7 +23,10 @@ define([ this._selectContainer.enabled = false; this._container.appendChild(this._selectContainer); - this._pubSub.subscribe('allFontsLoaded', this._onAllFontsLoaded.bind(this)); + this._pubSub.subscribe('allFontsLoaded', this._updateOptions.bind(this)); + this._pubSub.subscribe('loadFont', this._updateOptions.bind(this)); + this._pubSub.subscribe('unloadFont', this._updateOptions.bind(this)); + this._pubSub.subscribe('activateFont', this._onActivateFont.bind(this)); } var _p = FontLister.prototype = Object.create(Parent.prototype); @@ -32,40 +36,45 @@ define([ order: 'load' // OR: 'family' }; - _p._onActivateFont = function (fontIndex) { - var i,l - , options = this._selectContainer.children - , option - ; - for(i=0,l=options.length;iobj.sizes); + this._textLineTemplate = this._container.querySelector( + this._options.textLineTemplateSelector); + this._columnTemplate = this._container.querySelector( + this._options.columnTemplateSelector); + this[Parent.$DESTRUCTORS] = false; + this._samples = new Set(); + this._initColumns(); + // just use one handler to collect all input events as they bubble + this._container.addEventListener('input', this._onInput.bind(this), true); + } + + var _p = DataColumns.prototype = Object.create(Parent.prototype); + _p.constructor = DataColumns; + + DataColumns.defaultOptions = { + fontSizeSelector: '.font-testing-data__font-size' + , textLineTemplateSelector: 'template.font-testing-data__textline' + , columnTemplateSelector: 'template.font-testing-data__column' + , sampleTag: 'p' + , sampleClass: 'font-testing-data__sample' + }; + + _p._initColumns = function() { + var columns = []; + for (let sizes of this._columnSizes) { + let column + , items = [] + ; + + if(this._columnTemplate) { + column = this._columnTemplate.content.cloneNode(true); + columns.push(column); + } + else + // if there's no column template, fall back to the container + // ALSO: no mutli columns possible! + column = this._container; + for(let size of sizes) { + let fontsizeLabel = `${size} px` + , setFontSize = el=>el.fontSize=fontsize //jshint ignore:line + , item = this._textLineTemplate.content.cloneNode(true) + , sample = domTool.createElement(this._options.sampleTag + , { + 'class': this._options.sampleClass + , contenteditable: 'true' + , style: `font-size: ${size}px` + } + , this._textContent); + this._samples.add(sample); + // e.g.: + //

+ //

+ // + //

+ domTool.insertAtMarkerComment(item, 'insert: font size' + , domTool.createTextNode(fontsizeLabel)); + domTool.insertAtMarkerComment(item, 'insert: sample', sample); + items.push(item); + } + domTool.insertAtMarkerComment(column + , 'insert: textline' + , domTool.createFragment(items, false)); + } + if(columns.length) + // must insert at the end, otherwise, the documentFragment + // is empty and we can't use it to insert the samples. + // Also good to keep the correct order. + domTool.insertAtMarkerComment(this._container + , 'insert: columns' + , domTool.createFragment(columns, false)); + }; + + _p._onInput = function(e) { + if(!this._samples.has(e.target)) + // really only use changes occuring to our samples. + return; + this._changeText(e.target.textContent); + }; + + _p._changeText = function (newText) { + if(this._textContent === newText) + return; + this._textContent = newText; + for(let sample of this._samples) { + if(sample.ownerDocument.activeElement === sample) + // need this or we loose the focus/prompt position + continue; + sample.textContent = newText; + } + }; + + return DataColumns; +}); diff --git a/lib/widgets/GlyphTables.js b/lib/widgets/GlyphTables.js index a45b4b1..a430809 100644 --- a/lib/widgets/GlyphTables.js +++ b/lib/widgets/GlyphTables.js @@ -1,3 +1,4 @@ +// jshint esversion:6 define([ 'specimenTools/_BaseWidget' , './GlyphTable' @@ -36,11 +37,12 @@ define([ this._options = this._makeOptions(options); - this._tables = []; + this._tables = new Map(); this._tablesContainer = this._container.ownerDocument.createElement('div'); this._container.appendChild(this._tablesContainer); this._pubSub.subscribe('loadFont', this._onLoadFont.bind(this)); + this._pubSub.subscribe('unloadFont', this._onUnloadFont.bind(this)); this._pubSub.subscribe('activateFont', this._onActivateFont.bind(this)); this._pubSub.subscribe('allFontsLoaded', this._onAllFontsLoaded.bind(this)); } @@ -52,34 +54,50 @@ define([ glyphTable: {} }; - _p._onLoadFont = function (i, fontFileName, font) { - var gt = new GlyphTable(this._tablesContainer.ownerDocument, font, this._options.glyphTable); - this._tables[i] = gt; + _p._onLoadFont = function (id, fontFileName, font) { + if(this._tables.has(id)) + this._onUnloadFont(id); + let gt = new GlyphTable(this._tablesContainer.ownerDocument, font, this._options.glyphTable); + this._tables.set(id, gt); + if(this._activeTable === id) + this._onActivateFont(id); + + }; + + _p._onUnloadFont = function (id) { + var table = this._tables.get(id); + if(!table) + return; + this._tables.delete(id); + table.deactivate(); + if(table.element && table.element.parentNode) + table.element.parentNode.removeChild(table.element); }; _p._onAllFontsLoaded = function(countAll) { /*jshint unused:vars*/ - var i, l, dimensions, ascent = null, descent = null, width = null; - for(i=0,l=this._tables.length;i{ + var html = mustache.render(node.textContent, this._view) + , fragment = domTool.createFragmentFromHTML(html, this._options.domPurifyTrusted) + ; + // just insert in place + domTool.insertAfter(fragment, node); + }); + + } + + var _p = Mustache.prototype = Object.create(Parent.prototype); + _p.constructor = Mustache; + + Mustache.defaultOptions = { + templateClass: 'mustache__template' + // config for the domTool.createFragmentFromHTML "trusted" argument + , domPurifyTrusted: false + }; + + return Mustache; +}); diff --git a/lib/widgets/PerFont.js b/lib/widgets/PerFont.js index 2f7bdc2..3fd49df 100644 --- a/lib/widgets/PerFont.js +++ b/lib/widgets/PerFont.js @@ -1,3 +1,4 @@ +/* jshint esversion:6 */ define([ 'specimenTools/_BaseWidget' ], function( @@ -21,7 +22,14 @@ define([ this._pubSub = pubSub; this._fontsData = fontsData; this._webFontProvider = webFontProvider; - this._pubSub.subscribe('allFontsLoaded', this._onAllFontsLoaded.bind(this)); + + if(this._options['events.allFontsLoaded']) + this._pubSub.subscribe('allFontsLoaded', this._onAllFontsLoaded.bind(this)); + else { + this._pubSub.subscribe('loadFont', this._onLoadFont.bind(this)); + this._pubSub.subscribe('unloadFont', this._onUnloadFont.bind(this)); + } + this._contentElements = []; this._bluePrintNodes = this._getBluePrintNodes(); } @@ -35,6 +43,7 @@ define([ , itemClass: 'per-font__item' , fontDataClass: 'per-font__data' , currentFontClass: 'per-font__current-font' + , 'events.allFontsLoaded': true }; _p._getBluePrintNodes = function() { @@ -158,21 +167,28 @@ define([ return items; }; - _p._onAllFontsLoaded = function(numberAllFonts) { - //jshint unused:vars - var fonts = this._fontsData.getFontIndexesInFamilyOrder() - , items, i, l - ; - - for(i=this._contentElements.length-1;i>=0;i--) - this._contentElements[i].parentNode.removeChild(this._contentElements[i]); + _p._onAllFontsLoaded = function(/* numberAllFonts */) { + var fonts = this._fontsData.getFontIdsInFamilyOrder(); + for(let contentElement of this._contentElements) + contentElement.parentNode.removeChild(contentElement); + this._contentElements.splice(0, Infinity); - for(i=0,l=fonts.length;ithis._activateFont(id), true); + this._switches[id] = button; this._switchesContainer.appendChild(button); }; - _p._onLoadFont = function (i, fontFileName, font) { + _p._onLoadFont = function (id, fontFileName, font) { /*jshint unused: vars*/ - this._switches[i].disabled = false; + if(id in this._switches) + this._switches[id].disabled = false; + }; + + _p._onUnloadFont = function (id) { + if(!this._switches[id]) + return; + this._switchesContainer.removeChild(this._switches[id]); + delete this._switches[id]; }; - _p._activateFont = function(i) { + _p._activateFont = function(id) { // this will call this._onActivateFont - this._pubSub.publish('activateFont', i); + this._pubSub.publish('activateFont', id); }; - _p._onActivateFont = function(i) { + _p._onActivateFont = function(id) { /*jshint unused: vars*/ // this should only change the view, not emit signals // ToDo: mark the button(s) active/inactive diff --git a/lib/widgets/SubSpecimenController.js b/lib/widgets/SubSpecimenController.js new file mode 100644 index 0000000..2d2caca --- /dev/null +++ b/lib/widgets/SubSpecimenController.js @@ -0,0 +1,490 @@ +define([ + 'specimenTools/_BaseWidget' + , 'specimenTools/services/PubSub' + , 'specimenTools/initWidgets' + , 'specimenTools/services/dom-tool' +], function( + Parent + , PubSub + , initWidgets + , domTool +) { + "use strict"; + /*jshint esnext:true*/ + + /** + * Load sub-specimen from a selection menu. + */ + function SubSpecimenController(container, pubSub, fontsLoadState + , remoteLoader, widgetDependencies, options) { + Parent.call(this, options); + + this._container = container; + this._pubSub = pubSub; + // used to initate a sub-specimen + this._fontsLoadState = fontsLoadState; + this._remoteLoader = remoteLoader; + + // should this._subPubSub publish to this._pubSub? + // e.g. to activate a different font? + this._subPubSub = new PubSub(); + + // expecting an html