From: Marek Stępniowski Date: Thu, 14 Aug 2008 13:09:41 +0000 (+0200) Subject: Wstępny import. X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/8559c95597de98e8f6c580e97224ed3ecc9dc5c0 Wstępny import. --- 8559c95597de98e8f6c580e97224ed3ecc9dc5c0 diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 000000000..280bd03c5 Binary files /dev/null and b/.DS_Store differ diff --git a/.hgignore.swp b/.hgignore.swp new file mode 100644 index 000000000..0ec46619c Binary files /dev/null and b/.hgignore.swp differ diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..d5e908b7c --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +deploy: + rsync -vzr --delete --exclude="*.pyc" --exclude="/lxml" --exclude=".svn" --exclude="/lektury.sqlite" --exclude="/settings.py" . zuber@continental.dreamhost.com:django_projects/wolnelektury + ssh zuber@continental.dreamhost.com 'touch ~/wolnelektury.stepniowski.com/dispatch.fcgi' \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/books/.DS_Store b/books/.DS_Store new file mode 100755 index 000000000..27189cc4e Binary files /dev/null and b/books/.DS_Store differ diff --git a/books/Bajki_i_przypowiesci_Czesc_czwarta.xml b/books/Bajki_i_przypowiesci_Czesc_czwarta.xml new file mode 100755 index 000000000..4cad94bbb --- /dev/null +++ b/books/Bajki_i_przypowiesci_Czesc_czwarta.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki i przypowieści (4) +Bajki i przypowieści +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP2 +G +L +pol + + + diff --git a/books/Bajki_i_przypowiesci_Czesc_druga.xml b/books/Bajki_i_przypowiesci_Czesc_druga.xml new file mode 100755 index 000000000..ec00cd779 --- /dev/null +++ b/books/Bajki_i_przypowiesci_Czesc_druga.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki i przypowieści (2) +Bajki i przypowieści +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP2 +G +L +pol + + + diff --git a/books/Bajki_i_przypowiesci_Czesc_pierwsza.xml b/books/Bajki_i_przypowiesci_Czesc_pierwsza.xml new file mode 100755 index 000000000..8939834ca --- /dev/null +++ b/books/Bajki_i_przypowiesci_Czesc_pierwsza.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki i przypowieści (1) +Bajki i przypowieści +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP2 +G +L +pol + + + diff --git a/books/Bajki_i_przypowiesci_Czesc_trzecia.xml b/books/Bajki_i_przypowiesci_Czesc_trzecia.xml new file mode 100755 index 000000000..fa1bc602a --- /dev/null +++ b/books/Bajki_i_przypowiesci_Czesc_trzecia.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki i przypowieści (3) +Bajki i przypowieści +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP2 +G +L +pol + + + diff --git a/books/Bajki_nowe_Czesc_czwarta.xml b/books/Bajki_nowe_Czesc_czwarta.xml new file mode 100755 index 000000000..205ed0edc --- /dev/null +++ b/books/Bajki_nowe_Czesc_czwarta.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki nowe (4) +Bajki nowe +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP2 +G +L +pol + + + diff --git a/books/Bajki_nowe_Czesc_druga.xml b/books/Bajki_nowe_Czesc_druga.xml new file mode 100755 index 000000000..7bda731fa --- /dev/null +++ b/books/Bajki_nowe_Czesc_druga.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki nowe (2) +Bajki nowe +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP2 +G +L +pol + + + diff --git a/books/Bajki_nowe_Czesc_pierwsza.xml b/books/Bajki_nowe_Czesc_pierwsza.xml new file mode 100755 index 000000000..750199f43 --- /dev/null +++ b/books/Bajki_nowe_Czesc_pierwsza.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki nowe (1) +Bajki nowe +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP2 +G +L +pol + + + diff --git a/books/Bajki_nowe_Czesc_trzecia.xml b/books/Bajki_nowe_Czesc_trzecia.xml new file mode 100755 index 000000000..55ad09fa6 --- /dev/null +++ b/books/Bajki_nowe_Czesc_trzecia.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki nowe (3) +Bajki nowe +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP2 +G +L +pol + + + diff --git a/books/Cierpienia_mlodego_Wertera.xml b/books/Cierpienia_mlodego_Wertera.xml new file mode 100755 index 000000000..2a70fb2df --- /dev/null +++ b/books/Cierpienia_mlodego_Wertera.xml @@ -0,0 +1,29 @@ + + + +Goethe, Johann Wolfgang von +Cierpienia młodego Wertera +Mirandola, Franciszek +Zygmunt, Zagórowski +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Epika +Powieść epistolarna +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Cierpienia+m%C5%82odego+Wertera +http://www.polona.pl/Content/3770 +Goethe, Johann Wolfgang von (1749-1832), Cierpienia młodego Wertera, tłum. Franciszek Mirandola, oprac. Zygmunt Zagórowski, Krakowska Spółka Wydawnicza, Kraków, 1922 +Domena publiczna - Johann Wolfgang von Goethe zm. 1832 +1832 +xml +text +text +2008-02-27 +L +pol + + + diff --git a/books/Dusiolek.xml b/books/Dusiolek.xml new file mode 100755 index 000000000..8c4f4b968 --- /dev/null +++ b/books/Dusiolek.xml @@ -0,0 +1,32 @@ + + + +Leśmian, Bolesław +Dusiołek +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Młoda Polska +Dwudziestolecie międzywojenne +Liryka +Epika +Ballada +Wiersz +Wiersz sylabotoniczny +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Dusio%C5%82ek +http://www.polona.pl/dlibra/doccontent2?id=7336&from=&from=generalsearch&dirids=1&lang=pl +Bolesław Leśmian (1877-1937), Łąka, Wydawnictwo Mortkowicza, Warszawa, 1920 +Domena publiczna - Bolesław Leśmian zm. 1937 +1937 +xml +text +text +2008-01-11 +G +L +pol + + + diff --git a/books/Dziewczyna.xml b/books/Dziewczyna.xml new file mode 100755 index 000000000..b5c66cf95 --- /dev/null +++ b/books/Dziewczyna.xml @@ -0,0 +1,31 @@ + + + +Leśmian, Bolesław +Dziewczyna +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Młoda Polska +Dwudziestolecie międzywojenne +Liryka +Epika +Ballada +Wiersz +Wiersz sylabotoniczny +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Dziewczyna +Bolesław Leśmian (1877-1937), Napój cienisty, Wydawnictwo Mortkowicza, Warszawa, 1936 +Domena publiczna - Bolesław Leśmian zm. 1937 +1937 +xml +text +text +2008-01-11 +G +L +pol + + + diff --git a/books/Fraszki_Ksiegi_pierwsze.xml b/books/Fraszki_Ksiegi_pierwsze.xml new file mode 100755 index 000000000..f2569b970 --- /dev/null +++ b/books/Fraszki_Ksiegi_pierwsze.xml @@ -0,0 +1,33 @@ + + + +Kochanowski, Jan +Fraszki - Księgi 1 +Fraszki +Krzyżanowski, Julian +Otwinowska, Barbara +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Fraszka +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=1499&from=editionindex&dirids=1 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Kochanowski zm. 1584 +1584 +xml +text +text +2007-09-07 +SP2 +G +L +pol + + + diff --git a/books/Fraszki_Ksiegi_trzecie.xml b/books/Fraszki_Ksiegi_trzecie.xml new file mode 100755 index 000000000..42c5b8a70 --- /dev/null +++ b/books/Fraszki_Ksiegi_trzecie.xml @@ -0,0 +1,33 @@ + + + +Kochanowski, Jan +Fraszki - Księgi 3 +Fraszki +Krzyżanowski, Julian +Otwinowska, Barbara +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Fraszka +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=1499&from=editionindex&dirids=1 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Kochanowski zm. 1584 +1584 +xml +text +text +2007-09-07 +SP2 +G +L +pol + + + diff --git a/books/Fraszki_Ksiegi_wtore.xml b/books/Fraszki_Ksiegi_wtore.xml new file mode 100755 index 000000000..d84e990a3 --- /dev/null +++ b/books/Fraszki_Ksiegi_wtore.xml @@ -0,0 +1,32 @@ + + + +Kochanowski, Jan +Fraszki - Księgi 2 +Fraszki +Krzyżanowski, Julian +Otwinowska, Barbara +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Fraszka +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=1499&from=editionindex&dirids=1 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Kochanowski zm. 1584 +1584 +xml +text +text +2007-09-07 +G +L +pol + + + diff --git a/books/Fraszki_dodane.xml b/books/Fraszki_dodane.xml new file mode 100755 index 000000000..d87ea17b9 --- /dev/null +++ b/books/Fraszki_dodane.xml @@ -0,0 +1,32 @@ + + + +Kochanowski, Jan +Fraszki - Utwory dodane +Fraszki +Krzyżanowski, Julian +Otwinowska, Barbara +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Fraszka +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=1499&from=editionindex&dirids=1 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Kochanowski zm. 1584 +1584 +xml +text +text +2007-09-07 +G +L +pol + + + diff --git a/books/Moralnosc_pani_Dulskiej.xml b/books/Moralnosc_pani_Dulskiej.xml new file mode 100755 index 000000000..80842d6e9 --- /dev/null +++ b/books/Moralnosc_pani_Dulskiej.xml @@ -0,0 +1,29 @@ + + + +Zapolska, Gabriela +Moralność pani Dulskiej +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Dramat +Tragifarsa +Komedia +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Moralno%C5%9B%C4%87+pani+Dulskiej +http://www.polona.pl/dlibra/doccontent2?id=582&from=&from=generalsearch&dirids=1&lang=pl +Zapolska, Gabriela (1857-1921), Moralność pani Dulskiej: komedya w trzech aktach, Tow. Akc. S. Orgelbranda S-ów, Warszawa, 1907 +Domena publiczna - Gabriela Zapolska, herbu Korwin, właśc. Maria Gabriela Korwin-Piotro, zm. 17 grudnia 1921 +1921 +xml +text +text +2007-11-10 +G +L +pol + + + diff --git a/books/Nie-Boska_komedia.xml b/books/Nie-Boska_komedia.xml new file mode 100755 index 000000000..94820e1ab --- /dev/null +++ b/books/Nie-Boska_komedia.xml @@ -0,0 +1,27 @@ + + + +Krasiński, Zygmunt +Nie-Boska komedia +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Dramat +Dramat romantyczny +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Nie-boska+komedia +http://www.polona.pl/dlibra/doccontent2?id=592 +Krasiński, Zygmunt (1812-1859), Nie-Boska komedia, Zakład Narodowy im. Ossolińskich, wyd. 8 zmien., Wrocław, 1965 +Domena publiczna - Zygmunt Krasiński zm. 1859 +1859 +xml +text +text +2007-11-10 +L +pol + + + diff --git a/books/Poeta.xml b/books/Poeta.xml new file mode 100755 index 000000000..28629f0cc --- /dev/null +++ b/books/Poeta.xml @@ -0,0 +1,28 @@ + + + +Leśmian, Bolesław +Poeta +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Młoda Polska +Dwudziestolecie międzywojenne +Liryka +Wiersz +Wiersz sylabotoniczny +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Poeta +Bolesław Leśmian (1877-1937), Napój cienisty, Wydawnictwo Mortkowicza, Warszawa, 1936 +Domena publiczna - Bolesław Leśmian zm. 1937 +1937 +xml +text +text +2008-01-11 +L +pol + + + diff --git a/books/Przedwiosnie.xml b/books/Przedwiosnie.xml new file mode 100755 index 000000000..961ed5740 --- /dev/null +++ b/books/Przedwiosnie.xml @@ -0,0 +1,28 @@ + + + +Å»eromski, Stefan +Przedwiośnie +Sekuła, Aleksandra +Markiewicz, Henryk +Pigoń, Stanisław +Sobczyński, Mariusz +Fundacja Nowoczesna Polska +Dwudziestolecie międzywojenne +Epika +Powieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Przedwio%C5%9Bnie +Stefan Å»eromski (1864-1925), Przedwiośnie, Czytelnik, Warszawa, 1976 +Domena publiczna - Stefan Å»eromski zm. 1925 +1925 +xml +text +text +2008-04-10 +L +pol + + + diff --git a/books/Przydatek_do_Bajek_i_przypowiesci.xml b/books/Przydatek_do_Bajek_i_przypowiesci.xml new file mode 100755 index 000000000..7dd731363 --- /dev/null +++ b/books/Przydatek_do_Bajek_i_przypowiesci.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki i przypowieści (5) - przydatek +Bajki i przypowieści +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP2 +G +L +pol + + + diff --git a/books/Przydatek_do_Bajek_nowych.xml b/books/Przydatek_do_Bajek_nowych.xml new file mode 100755 index 000000000..6db8b739a --- /dev/null +++ b/books/Przydatek_do_Bajek_nowych.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki nowe (5) - przydatek +Bajki nowe +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP2 +G +L +pol + + + diff --git a/books/Romeo_i_Julia.xml b/books/Romeo_i_Julia.xml new file mode 100755 index 000000000..389ee86e5 --- /dev/null +++ b/books/Romeo_i_Julia.xml @@ -0,0 +1,31 @@ + + + +Shakespeare, William +Romeo i Julia +Paszkowski, Józef +Jabłkowska, Róża +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Renesans +Dramat +Dramat szekspirowski +Tragedia +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Romeo+i+Julia +http://www.polona.pl/Content/3719 +Shakespeare, William (1564-1616), Romeo i Julia, Państwowy Instytut Wydawniczy, wyd. 5, Warszawa, 1975 +Domena publiczna - tłumacz Józef Paszkowski zm. 1861 +1861 +xml +text +text +2007-08-31 +G +L +pol + + + diff --git a/books/Satyry_Cz1_Do_krola.xml b/books/Satyry_Cz1_Do_krola.xml new file mode 100755 index 000000000..d89e282c2 --- /dev/null +++ b/books/Satyry_Cz1_Do_krola.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (1) Do króla +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Gracz.xml b/books/Satyry_Cz1_Gracz.xml new file mode 100755 index 000000000..d51e1fe0a --- /dev/null +++ b/books/Satyry_Cz1_Gracz.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (12) Gracz +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Marnotrawstwo.xml b/books/Satyry_Cz1_Marnotrawstwo.xml new file mode 100755 index 000000000..8c428a406 --- /dev/null +++ b/books/Satyry_Cz1_Marnotrawstwo.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (5) Marnotrawstwo +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Oszczednosc.xml b/books/Satyry_Cz1_Oszczednosc.xml new file mode 100755 index 000000000..23249c422 --- /dev/null +++ b/books/Satyry_Cz1_Oszczednosc.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (6) Oszczędność +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Palinodia.xml b/books/Satyry_Cz1_Palinodia.xml new file mode 100755 index 000000000..50270d579 --- /dev/null +++ b/books/Satyry_Cz1_Palinodia.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (13) Palinodia +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Pan_niewart_slugi.xml b/books/Satyry_Cz1_Pan_niewart_slugi.xml new file mode 100755 index 000000000..7a5e1986d --- /dev/null +++ b/books/Satyry_Cz1_Pan_niewart_slugi.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (11) Pan niewart sługi +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Pijanstwo.xml b/books/Satyry_Cz1_Pijanstwo.xml new file mode 100755 index 000000000..5925ed5df --- /dev/null +++ b/books/Satyry_Cz1_Pijanstwo.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (7) Pijaństwo +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Przestroga_mlodemu.xml b/books/Satyry_Cz1_Przestroga_mlodemu.xml new file mode 100755 index 000000000..ac9890b0e --- /dev/null +++ b/books/Satyry_Cz1_Przestroga_mlodemu.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (8) Przestroga młodemu +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Swiat_zepsuty.xml b/books/Satyry_Cz1_Swiat_zepsuty.xml new file mode 100755 index 000000000..f66c350c1 --- /dev/null +++ b/books/Satyry_Cz1_Swiat_zepsuty.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (2) Świat zepsuty +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Szczesliwosc_filutow.xml b/books/Satyry_Cz1_Szczesliwosc_filutow.xml new file mode 100755 index 000000000..7739e3b33 --- /dev/null +++ b/books/Satyry_Cz1_Szczesliwosc_filutow.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (4) Szczęśliwość filutów +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Zlosc_ukryta_i_jawna.xml b/books/Satyry_Cz1_Zlosc_ukryta_i_jawna.xml new file mode 100755 index 000000000..dcafb927c --- /dev/null +++ b/books/Satyry_Cz1_Zlosc_ukryta_i_jawna.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (3) Złość ukryta i jawna +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz1_Zona_modna.xml b/books/Satyry_Cz1_Zona_modna.xml new file mode 100755 index 000000000..0330972ad --- /dev/null +++ b/books/Satyry_Cz1_Zona_modna.xml @@ -0,0 +1,28 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (9) Å»ona modna +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +G +L +pol + + + diff --git a/books/Satyry_Cz1_Zycie_dworskie.xml b/books/Satyry_Cz1_Zycie_dworskie.xml new file mode 100755 index 000000000..5e1bd84a1 --- /dev/null +++ b/books/Satyry_Cz1_Zycie_dworskie.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 1 - (10) Å»ycie dworskie +Sekuła, Aleksandra +Hernas, Marcin +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz2_Czlowiek_i_zwierz.xml b/books/Satyry_Cz2_Czlowiek_i_zwierz.xml new file mode 100755 index 000000000..5847ef18b --- /dev/null +++ b/books/Satyry_Cz2_Czlowiek_i_zwierz.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 2 - (5) Człowiek i zwierz +Sekuła, Aleksandra +Sobczyński, Mariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz2_Klatki.xml b/books/Satyry_Cz2_Klatki.xml new file mode 100755 index 000000000..764587ebc --- /dev/null +++ b/books/Satyry_Cz2_Klatki.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 2 - (6) Klatki +Sekuła, Aleksandra +Sobczyński, Mariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz2_Malzenstwo.xml b/books/Satyry_Cz2_Malzenstwo.xml new file mode 100755 index 000000000..6f2e2aec6 --- /dev/null +++ b/books/Satyry_Cz2_Malzenstwo.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 2 - (8) Małżeństwo +Sekuła, Aleksandra +Sobczyński, Mariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz2_Medrek.xml b/books/Satyry_Cz2_Medrek.xml new file mode 100755 index 000000000..14344845d --- /dev/null +++ b/books/Satyry_Cz2_Medrek.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 2 - (7) Mędrek +Sekuła, Aleksandra +Sobczyński, Mariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz2_Pochwala_glupstwa.xml b/books/Satyry_Cz2_Pochwala_glupstwa.xml new file mode 100755 index 000000000..d6218996e --- /dev/null +++ b/books/Satyry_Cz2_Pochwala_glupstwa.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 2 - (3) Pochwała głupstwa +Sekuła, Aleksandra +Sobczyński, Mariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz2_Pochwala_wieku.xml b/books/Satyry_Cz2_Pochwala_wieku.xml new file mode 100755 index 000000000..16859dd00 --- /dev/null +++ b/books/Satyry_Cz2_Pochwala_wieku.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 2 - (2) Pochwała wieku +Sekuła, Aleksandra +Sobczyński, Mariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz2_Pochwaly_milczenia.xml b/books/Satyry_Cz2_Pochwaly_milczenia.xml new file mode 100755 index 000000000..0c52aebbd --- /dev/null +++ b/books/Satyry_Cz2_Pochwaly_milczenia.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 2 - (1) Pochwały milczenia +Sekuła, Aleksandra +Sobczyński, Mariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz2_Podroz.xml b/books/Satyry_Cz2_Podroz.xml new file mode 100755 index 000000000..4e0f3e546 --- /dev/null +++ b/books/Satyry_Cz2_Podroz.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 2 - (9) Podróż +Sekuła, Aleksandra +Sobczyński, Mariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Satyry_Cz2_Wzietosc.xml b/books/Satyry_Cz2_Wzietosc.xml new file mode 100755 index 000000000..aa8e9f712 --- /dev/null +++ b/books/Satyry_Cz2_Wzietosc.xml @@ -0,0 +1,27 @@ + + + +Krasicki, Ignacy +Satyry - Część 2 - (4) Wziętość +Sekuła, Aleksandra +Sobczyński, Mariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Satyra +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3761&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Satyry i listy, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, wyd. 1, Wrocław, 1958 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2008-02-12 +L +pol + + + diff --git a/books/Sonety_krymskie_00_Motto_i_dedykacja.xml b/books/Sonety_krymskie_00_Motto_i_dedykacja.xml new file mode 100755 index 000000000..574801343 --- /dev/null +++ b/books/Sonety_krymskie_00_Motto_i_dedykacja.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (00) Motto i dedykacja +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_01_Stepy_akermanskie.xml b/books/Sonety_krymskie_01_Stepy_akermanskie.xml new file mode 100755 index 000000000..0677af010 --- /dev/null +++ b/books/Sonety_krymskie_01_Stepy_akermanskie.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (01) Stepy akermańskie +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_02_Cisza_morska.xml b/books/Sonety_krymskie_02_Cisza_morska.xml new file mode 100755 index 000000000..6a9ceb7ee --- /dev/null +++ b/books/Sonety_krymskie_02_Cisza_morska.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (02) Cisza morska +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_03_Zegluga.xml b/books/Sonety_krymskie_03_Zegluga.xml new file mode 100755 index 000000000..aac2431c2 --- /dev/null +++ b/books/Sonety_krymskie_03_Zegluga.xml @@ -0,0 +1,29 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (03) Å»egluga +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798 - 1855) Poezje, Tom 2, Wiersze z lat 1825 - 1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2, popr., druk. W. L. Anczyca, Kraków 1928 +OPIS STANU PRAWNEGO TEKSTU +1855 +xml +text +text +2008-01-29 +POZIOM NAUCZANIA +POZIOM NAUCZANIA +pol + + + diff --git a/books/Sonety_krymskie_04_Burza.xml b/books/Sonety_krymskie_04_Burza.xml new file mode 100755 index 000000000..26cb75802 --- /dev/null +++ b/books/Sonety_krymskie_04_Burza.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (04) Burza +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_05_Widok_gor_ze_stepow_Kozlowa.xml b/books/Sonety_krymskie_05_Widok_gor_ze_stepow_Kozlowa.xml new file mode 100755 index 000000000..a88b402f1 --- /dev/null +++ b/books/Sonety_krymskie_05_Widok_gor_ze_stepow_Kozlowa.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (05) Widok gór ze stepów Kozłowa +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_06_Bakczysaraj.xml b/books/Sonety_krymskie_06_Bakczysaraj.xml new file mode 100755 index 000000000..36e47160b --- /dev/null +++ b/books/Sonety_krymskie_06_Bakczysaraj.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (06) Bakczysaraj +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_07_Bakczysaraj_w_nocy.xml b/books/Sonety_krymskie_07_Bakczysaraj_w_nocy.xml new file mode 100755 index 000000000..204d4d6a5 --- /dev/null +++ b/books/Sonety_krymskie_07_Bakczysaraj_w_nocy.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (07) Bakczysaraj w nocy +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_08_Grob_Potockiej.xml b/books/Sonety_krymskie_08_Grob_Potockiej.xml new file mode 100755 index 000000000..70236a8dc --- /dev/null +++ b/books/Sonety_krymskie_08_Grob_Potockiej.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (08) Grób Potockiej +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_09_Mogily_haremu.xml b/books/Sonety_krymskie_09_Mogily_haremu.xml new file mode 100755 index 000000000..2549b7e88 --- /dev/null +++ b/books/Sonety_krymskie_09_Mogily_haremu.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (09) Mogiły haremu +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_10_Bajdary.xml b/books/Sonety_krymskie_10_Bajdary.xml new file mode 100755 index 000000000..70d573f4d --- /dev/null +++ b/books/Sonety_krymskie_10_Bajdary.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (10) Bajdary +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_11_Aluszta_w_dzien.xml b/books/Sonety_krymskie_11_Aluszta_w_dzien.xml new file mode 100755 index 000000000..600b678f0 --- /dev/null +++ b/books/Sonety_krymskie_11_Aluszta_w_dzien.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (11) Ałuszta w dzień +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_12_Aluszta_w_nocy.xml b/books/Sonety_krymskie_12_Aluszta_w_nocy.xml new file mode 100755 index 000000000..3b1cad46f --- /dev/null +++ b/books/Sonety_krymskie_12_Aluszta_w_nocy.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (12) Ałuszta w nocy +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_13_Czatyrdah.xml b/books/Sonety_krymskie_13_Czatyrdah.xml new file mode 100755 index 000000000..7867aa31f --- /dev/null +++ b/books/Sonety_krymskie_13_Czatyrdah.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (13) Czatyrdah +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_14_Pielgrzym.xml b/books/Sonety_krymskie_14_Pielgrzym.xml new file mode 100755 index 000000000..509f7c27b --- /dev/null +++ b/books/Sonety_krymskie_14_Pielgrzym.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (14) Pielgrzym +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_15_Droga_nad_przepascia_w_Czufut_Kale.xml b/books/Sonety_krymskie_15_Droga_nad_przepascia_w_Czufut_Kale.xml new file mode 100755 index 000000000..5fc3398b5 --- /dev/null +++ b/books/Sonety_krymskie_15_Droga_nad_przepascia_w_Czufut_Kale.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (15) Droga nad przepaścią w Czufut-Kale +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_16_Gora_Kikneis.xml b/books/Sonety_krymskie_16_Gora_Kikneis.xml new file mode 100755 index 000000000..35ec259aa --- /dev/null +++ b/books/Sonety_krymskie_16_Gora_Kikneis.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (16) Góra Kikineis +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_17_Ruiny_zamku_w_Balaklawie.xml b/books/Sonety_krymskie_17_Ruiny_zamku_w_Balaklawie.xml new file mode 100755 index 000000000..3011d249b --- /dev/null +++ b/books/Sonety_krymskie_17_Ruiny_zamku_w_Balaklawie.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (17) Ruiny zamku w Bałakławie +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Sonety_krymskie_18_Ajudah.xml b/books/Sonety_krymskie_18_Ajudah.xml new file mode 100755 index 000000000..44c22363e --- /dev/null +++ b/books/Sonety_krymskie_18_Ajudah.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Sonety krymskie - (18) Ajudah +Sonety krymskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=2223&from=editionindex&dirids=4 +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), wstęp i układ Józefa Kallenbacha, objaśn. zaopatrzył Jan Bystrzycki, Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., druk. W. L. Anczyca, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2008-01-29 +L +pol + + + diff --git a/books/Swidryga_i_Midryga.xml b/books/Swidryga_i_Midryga.xml new file mode 100755 index 000000000..020aa1baf --- /dev/null +++ b/books/Swidryga_i_Midryga.xml @@ -0,0 +1,29 @@ + + + +Leśmian, Bolesław +Świdryga i Midryga +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Młoda Polska +Dwudziestolecie międzywojenne +Liryka +Wiersz +Wiersz sylabotoniczny +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/%C5%9Awidryga+i+Midryga +http://www.polona.pl/dlibra/doccontent2?id=7336&from=&from=generalsearch&dirids=1&lang=pl +Bolesław Leśmian (1877-1937), Łąka, Wydawnictwo Mortkowicza, Warszawa, 1920 +Domena publiczna - Bolesław Leśmian zm. 1937 +1937 +xml +text +text +2008-01-11 +L +pol + + + diff --git a/books/Urszula_Kochanowska.xml b/books/Urszula_Kochanowska.xml new file mode 100755 index 000000000..fa8e0ce6a --- /dev/null +++ b/books/Urszula_Kochanowska.xml @@ -0,0 +1,28 @@ + + + +Leśmian, Bolesław +Urszula Kochanowska +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Młoda Polska +Dwudziestolecie międzywojenne +Liryka +Wiersz +Wiersz sylabotoniczny +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Urszula+Kochanowska +Bolesław Leśmian (1877-1937), Napój cienisty, Wydawnictwo Mortkowicza, Warszawa, 1936 +Domena publiczna - Bolesław Leśmian zm. 1937 +1937 +xml +text +text +2008-01-11 +G +pol + + + diff --git a/books/W_malinowym_chrusniaku.xml b/books/W_malinowym_chrusniaku.xml new file mode 100755 index 000000000..df0851c51 --- /dev/null +++ b/books/W_malinowym_chrusniaku.xml @@ -0,0 +1,30 @@ + + + +Leśmian, Bolesław +W malinowym chruśniaku +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Młoda Polska +Dwudziestolecie międzywojenne +Liryka +Wiersz +Wiersz sylabotoniczny +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/W+malinowym+chru%C5%9Bniaku +http://www.polona.pl/dlibra/doccontent2?id=7336&from=&from=generalsearch&dirids=1&lang=pl +Bolesław Leśmian (1877-1937), Łąka, Wydawnictwo Mortkowicza, Warszawa, 1920 +Domena publiczna - Bolesław Leśmian zm. 1937 +1937 +xml +text +text +2008-01-11 +G +L +pol + + + diff --git a/books/Wstep_do_Bajek_i_przypowiesci.xml b/books/Wstep_do_Bajek_i_przypowiesci.xml new file mode 100755 index 000000000..f254a71a7 --- /dev/null +++ b/books/Wstep_do_Bajek_i_przypowiesci.xml @@ -0,0 +1,33 @@ + + + +Krasicki, Ignacy +Bajki i przypowieści (0) - Wstęp +Bajki i przypowieści +Goliński, Zbigniew +Sekuła, Aleksandra +Sutkowska, Olga +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Oświecenie +Epika +Bajka +Przypowieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=3044&from=&from=generalsearch&dirids=1&lang=pl +Krasicki, Ignacy (1735-1801), Bajki, oprac. Zbigniew Goliński, Zakład Narodowy im. Ossolińskich, Kraków, 1975 +Domena publiczna - Ignacy Krasicki zm. 1801 +1801 +xml +text +text +2007-11-29 +SP1 +G +L +pol + + + diff --git a/books/andersen_brzydkie_kaczatko.xml b/books/andersen_brzydkie_kaczatko.xml new file mode 100755 index 000000000..8e1515856 --- /dev/null +++ b/books/andersen_brzydkie_kaczatko.xml @@ -0,0 +1,27 @@ + + + +Andersen, Hans Christian +Brzydkie kaczątko +Niewiadomska, Cecylia +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Romantyzm +Epika +Baśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Brzydkie+kacz%C4%85tko +http://www.polona.pl/dlibra/doccontent2?id=3563&dirids=4 +Andersen, Hans Christian (1805-1875), Baśnie, Gebethner i Wolff, wyd. 7, Kraków, 1925 +Domena publiczna - Cecylia Niewiadomska zm. 1925 +1925 +xml +text +text +2007-08-14 +SP1 +pol + + + diff --git a/books/andersen_krolowa_sniegu.xml b/books/andersen_krolowa_sniegu.xml new file mode 100755 index 000000000..28f5a6ec4 --- /dev/null +++ b/books/andersen_krolowa_sniegu.xml @@ -0,0 +1,27 @@ + + + +Andersen, Hans Christian +Królowa śniegu +Niewiadomska, Cecylia +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Romantyzm +Epika +Baśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Kr%C3%B3lowa+%C5%9Bniegu +http://www.polona.pl/dlibra/doccontent2?id=3563&dirids=4 +Andersen, Hans Christian (1805-1875), Baśnie, Gebethner i Wolff, wyd. 7, Kraków, 1925 +Domena publiczna - Cecylia Niewiadomska zm. 1925 +1925 +xml +text +text +2007-08-29 +SP1 +pol + + + diff --git a/books/asnyk_daremne_zale.xml b/books/asnyk_daremne_zale.xml new file mode 100755 index 000000000..2037e7f05 --- /dev/null +++ b/books/asnyk_daremne_zale.xml @@ -0,0 +1,27 @@ + + + +Asnyk, Adam +Daremne żale +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Pozytywizm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Daremne+%C5%BCale +http://www.polona.pl/Content/5164 +(Asnyk, Adam) El...y (1838-1897), Poezye, t. 3, Gebethner i Wolff, wyd. nowe poprzedzone słowem wstępnym St. Krzemińskiego, Warszawa, 1898 +Domena publiczna - Adam Asnyk zm. 1897 +1897 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/asnyk_miedzy_nami_nic_nie_bylo.xml b/books/asnyk_miedzy_nami_nic_nie_bylo.xml new file mode 100755 index 000000000..374fb9e24 --- /dev/null +++ b/books/asnyk_miedzy_nami_nic_nie_bylo.xml @@ -0,0 +1,27 @@ + + + +Asnyk, Adam +Między nami nic nie było +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Pozytywizm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Mi%C4%99dzy+nami+nic+nie+by%C5%82o +http://www.polona.pl/Content/5164 +(Asnyk, Adam) El...y (1838-1897), Poezye, t. 3, Gebethner i Wolff, wyd. nowe poprzedzone słowem wstępnym St. Krzemińskiego, Warszawa, 1898 +Domena publiczna - Adam Asnyk zm. 1897 +1897 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/asnyk_zaczarowana_krolewna.xml b/books/asnyk_zaczarowana_krolewna.xml new file mode 100755 index 000000000..08c6cdfd1 --- /dev/null +++ b/books/asnyk_zaczarowana_krolewna.xml @@ -0,0 +1,27 @@ + + + +Asnyk, Adam +Zaczarowana królewna +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Pozytywizm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Zaczarowana+kr%C3%B3lewna +http://www.polona.pl/Content/5164 +(Asnyk, Adam) El...y (1838-1897), Poezye, t. 3, Gebethner i Wolff, wyd. nowe poprzedzone słowem wstępnym St. Krzemińskiego, Warszawa, 1898 +Domena publiczna - Adam Asnyk zm. 1897 +1897 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/bogurodzica.xml b/books/bogurodzica.xml new file mode 100755 index 000000000..e9a6c1da6 --- /dev/null +++ b/books/bogurodzica.xml @@ -0,0 +1,30 @@ + + + +Anonim +Bogurodzica +Sekuła, Aleksandra +Feicht, Hieronim +Woronczak, Jerzy +Sutkowska, Olga +Fundacja Nowoczesna Polska +Średniowiecze +Liryka +Hymn +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Bogurodzica +http://www.polona.pl/Content/3073 +Bogurodzica, Biblioteka Pisarzów Polskich, Seria A, Liryka Średniowieczna, t. 1, Zakład Narodowy im. Ossolińskich. Wydawnictwo PAN, Wrocław, 1962 +Domena publiczna - Bogurodzica powstała we wczesnym średniowieczu, chociaż dokładna data jest nieznana. Przeważają hipotezy badaczy wskazujące na XI lub XII w. jako czas jej powstania. Pierwszy zapis tekstu jest późny, z początku XV w. (ok. 1407); wcześniejsze zapisy mogły zaginąć, ale też tekst mógł krążyć w obiegu ustnym. +1407 +xml +text +text +2007-09-06 +G +L +pol + + + diff --git a/books/fredro_zemsta.xml b/books/fredro_zemsta.xml new file mode 100755 index 000000000..05fa6c64c --- /dev/null +++ b/books/fredro_zemsta.xml @@ -0,0 +1,28 @@ + + + +Fredro, Aleksander +Zemsta +Maciejewski, Janusz +Sekuła, Aleksandra +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Romantyzm +Dramat +Komedia +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/3043 +Fredro, Aleksander (1793-1876), Zemsta, Wydawnictwo Łódź, wyd. 6, Łódź, 1975 +Aleksander Fredro zm. 1876 +1876 +xml +text +text +2007-08-30 +G +pol + + + diff --git a/books/kochanowski_odprawa_poslow_greckich.xml b/books/kochanowski_odprawa_poslow_greckich.xml new file mode 100755 index 000000000..1c89148e4 --- /dev/null +++ b/books/kochanowski_odprawa_poslow_greckich.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Odprawa posłów greckich +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Dramat +Tragedia +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Odprawa+pos%C5%82%C3%B3w+greckich +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_piesn1_I.xml b/books/kochanowski_piesn1_I.xml new file mode 100755 index 000000000..c126f354d --- /dev/null +++ b/books/kochanowski_piesn1_I.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń I (1) Byś wszystko złoto posiadł +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_II.xml b/books/kochanowski_piesn1_II.xml new file mode 100755 index 000000000..b6b47f95f --- /dev/null +++ b/books/kochanowski_piesn1_II.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Pieśń II (1) Serce roście patrząc na te czasy +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +G +L +pol + + + diff --git a/books/kochanowski_piesn1_III.xml b/books/kochanowski_piesn1_III.xml new file mode 100755 index 000000000..50aac6beb --- /dev/null +++ b/books/kochanowski_piesn1_III.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń III (1) Dzbanie mój pisany +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_IV.xml b/books/kochanowski_piesn1_IV.xml new file mode 100755 index 000000000..9fb0bd41b --- /dev/null +++ b/books/kochanowski_piesn1_IV.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń IV (1) Złota to strzała +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_IX.xml b/books/kochanowski_piesn1_IX.xml new file mode 100755 index 000000000..84678eb1d --- /dev/null +++ b/books/kochanowski_piesn1_IX.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń IX (1) Chcemy sobie być radzi +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_V.xml b/books/kochanowski_piesn1_V.xml new file mode 100755 index 000000000..e33b20f32 --- /dev/null +++ b/books/kochanowski_piesn1_V.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń V (1) Kto ma swego chleba +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_VI.xml b/books/kochanowski_piesn1_VI.xml new file mode 100755 index 000000000..5562d2a0b --- /dev/null +++ b/books/kochanowski_piesn1_VI.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń VI (1) Acz mię twa droga +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_VII.xml b/books/kochanowski_piesn1_VII.xml new file mode 100755 index 000000000..a2fac329a --- /dev/null +++ b/books/kochanowski_piesn1_VII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń VII (1) Trudna rada w tej mierze +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_VIII.xml b/books/kochanowski_piesn1_VIII.xml new file mode 100755 index 000000000..19345f2f4 --- /dev/null +++ b/books/kochanowski_piesn1_VIII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń VIII (1) Gdzieśkolwiek jest +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_X.xml b/books/kochanowski_piesn1_X.xml new file mode 100755 index 000000000..4e4db9693 --- /dev/null +++ b/books/kochanowski_piesn1_X.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń X (1) Kto mi dał skrzydła +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XI.xml b/books/kochanowski_piesn1_XI.xml new file mode 100755 index 000000000..56c1a8df5 --- /dev/null +++ b/books/kochanowski_piesn1_XI.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XI (1) Stronisz przede mną +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XII.xml b/books/kochanowski_piesn1_XII.xml new file mode 100755 index 000000000..3708bc85a --- /dev/null +++ b/books/kochanowski_piesn1_XII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XII (1) Muszę wyznać +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XIII.xml b/books/kochanowski_piesn1_XIII.xml new file mode 100755 index 000000000..7555e3117 --- /dev/null +++ b/books/kochanowski_piesn1_XIII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XIII (1) 0 piękna nocy nad zwyczaj +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XIV.xml b/books/kochanowski_piesn1_XIV.xml new file mode 100755 index 000000000..040c2f425 --- /dev/null +++ b/books/kochanowski_piesn1_XIV.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XIV (1) Patrzaj jako śnieg +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XIX.xml b/books/kochanowski_piesn1_XIX.xml new file mode 100755 index 000000000..02ef74cfc --- /dev/null +++ b/books/kochanowski_piesn1_XIX.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XIX (1) Å»al mi cię +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XV.xml b/books/kochanowski_piesn1_XV.xml new file mode 100755 index 000000000..1fdcb1df3 --- /dev/null +++ b/books/kochanowski_piesn1_XV.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XV (1) Nie za staraniem +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XVI.xml b/books/kochanowski_piesn1_XVI.xml new file mode 100755 index 000000000..fb3047669 --- /dev/null +++ b/books/kochanowski_piesn1_XVI.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XVI (1) Królom moc na poddane i zwierzchność +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XVII.xml b/books/kochanowski_piesn1_XVII.xml new file mode 100755 index 000000000..4fd13a427 --- /dev/null +++ b/books/kochanowski_piesn1_XVII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XVII (1) Słońce już padło +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XVIII.xml b/books/kochanowski_piesn1_XVIII.xml new file mode 100755 index 000000000..909eb5ea9 --- /dev/null +++ b/books/kochanowski_piesn1_XVIII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XVIII (1) Czołem za cześć +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XX.xml b/books/kochanowski_piesn1_XX.xml new file mode 100755 index 000000000..020186d21 --- /dev/null +++ b/books/kochanowski_piesn1_XX.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XX (1) Miło szaleć +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XXI.xml b/books/kochanowski_piesn1_XXI.xml new file mode 100755 index 000000000..a9e05147a --- /dev/null +++ b/books/kochanowski_piesn1_XXI.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XXI (1) Ty spisz +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XXII.xml b/books/kochanowski_piesn1_XXII.xml new file mode 100755 index 000000000..e1b633d8e --- /dev/null +++ b/books/kochanowski_piesn1_XXII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XXII (1) Rozumie mój +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XXIII.xml b/books/kochanowski_piesn1_XXIII.xml new file mode 100755 index 000000000..b7a8d18e8 --- /dev/null +++ b/books/kochanowski_piesn1_XXIII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XXIII (1) Nieźle czasem zamilczeć +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XXIV.xml b/books/kochanowski_piesn1_XXIV.xml new file mode 100755 index 000000000..3a538b180 --- /dev/null +++ b/books/kochanowski_piesn1_XXIV.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XXIV (1) Zegar słyszę wybija +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn1_XXV.xml b/books/kochanowski_piesn1_XXV.xml new file mode 100755 index 000000000..9cdc2dc1d --- /dev/null +++ b/books/kochanowski_piesn1_XXV.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XXV (1) Użałuj się +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_I.xml b/books/kochanowski_piesn2_I.xml new file mode 100755 index 000000000..77f80ec13 --- /dev/null +++ b/books/kochanowski_piesn2_I.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń I (2) Przeciwne chmury +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_II.xml b/books/kochanowski_piesn2_II.xml new file mode 100755 index 000000000..b266eba01 --- /dev/null +++ b/books/kochanowski_piesn2_II.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń II (2) Nie dbam aby zimne skały +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_III.xml b/books/kochanowski_piesn2_III.xml new file mode 100755 index 000000000..7ef61e14f --- /dev/null +++ b/books/kochanowski_piesn2_III.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń III (2) Nie wierz Fortunie +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_IV.xml b/books/kochanowski_piesn2_IV.xml new file mode 100755 index 000000000..49690c629 --- /dev/null +++ b/books/kochanowski_piesn2_IV.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń IV (2) W twardej kamiennej wieży +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_IX.xml b/books/kochanowski_piesn2_IX.xml new file mode 100755 index 000000000..db94ce424 --- /dev/null +++ b/books/kochanowski_piesn2_IX.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Pieśń IX (2) Nie porzucaj nadzieje +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +G +L +pol + + + diff --git a/books/kochanowski_piesn2_V.xml b/books/kochanowski_piesn2_V.xml new file mode 100755 index 000000000..d9b09d711 --- /dev/null +++ b/books/kochanowski_piesn2_V.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń V (2) Wieczna sromota +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_VI.xml b/books/kochanowski_piesn2_VI.xml new file mode 100755 index 000000000..f317b94ad --- /dev/null +++ b/books/kochanowski_piesn2_VI.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń VI (2) Królewno lutnie złotej +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_VII.xml b/books/kochanowski_piesn2_VII.xml new file mode 100755 index 000000000..fd0254473 --- /dev/null +++ b/books/kochanowski_piesn2_VII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń VII (2) Słońce pali +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_VIII.xml b/books/kochanowski_piesn2_VIII.xml new file mode 100755 index 000000000..ab44182a3 --- /dev/null +++ b/books/kochanowski_piesn2_VIII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń VIII (2) Nie frasuj sobie +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_X.xml b/books/kochanowski_piesn2_X.xml new file mode 100755 index 000000000..f4852e9be --- /dev/null +++ b/books/kochanowski_piesn2_X.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń X (2) Może kto ręką sławy dostać w boju +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XI.xml b/books/kochanowski_piesn2_XI.xml new file mode 100755 index 000000000..1bedb3af0 --- /dev/null +++ b/books/kochanowski_piesn2_XI.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XI (2) Stateczny umysł +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XII.xml b/books/kochanowski_piesn2_XII.xml new file mode 100755 index 000000000..5bca7ee57 --- /dev/null +++ b/books/kochanowski_piesn2_XII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XII (2) Nie masz i po drugi raz +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XIII.xml b/books/kochanowski_piesn2_XIII.xml new file mode 100755 index 000000000..b3750e2f3 --- /dev/null +++ b/books/kochanowski_piesn2_XIII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XIII (2) Panu dzięki oddawajmy +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XIV.xml b/books/kochanowski_piesn2_XIV.xml new file mode 100755 index 000000000..56684a391 --- /dev/null +++ b/books/kochanowski_piesn2_XIV.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XIV (2) Wy którzy pospolitą rzeczą władacie +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XIX.xml b/books/kochanowski_piesn2_XIX.xml new file mode 100755 index 000000000..8424e7804 --- /dev/null +++ b/books/kochanowski_piesn2_XIX.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XIX (2) Jest kto co by wzgardziwszy +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XV.xml b/books/kochanowski_piesn2_XV.xml new file mode 100755 index 000000000..15d6e7f12 --- /dev/null +++ b/books/kochanowski_piesn2_XV.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XV (2) Nie zawżdy Apollo +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XVI.xml b/books/kochanowski_piesn2_XVI.xml new file mode 100755 index 000000000..56a77d81c --- /dev/null +++ b/books/kochanowski_piesn2_XVI.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XVI (2) Nic po tych zbytnich potrawach +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XVII.xml b/books/kochanowski_piesn2_XVII.xml new file mode 100755 index 000000000..72a9ba86c --- /dev/null +++ b/books/kochanowski_piesn2_XVII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XVII (2) Niegodzien tego ten świat zawikłany +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XVIII.xml b/books/kochanowski_piesn2_XVIII.xml new file mode 100755 index 000000000..cfaec1ee7 --- /dev/null +++ b/books/kochanowski_piesn2_XVIII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XVIII (2) Ucieszna lutni +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XX.xml b/books/kochanowski_piesn2_XX.xml new file mode 100755 index 000000000..11b83d4f7 --- /dev/null +++ b/books/kochanowski_piesn2_XX.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XX (2) Jaką rozumiesz zazdrość zjednałaś sobie +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XXI.xml b/books/kochanowski_piesn2_XXI.xml new file mode 100755 index 000000000..f7a66f251 --- /dev/null +++ b/books/kochanowski_piesn2_XXI.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XXI (2) Srogie łańcuchy na swym sercu czuję +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XXII.xml b/books/kochanowski_piesn2_XXII.xml new file mode 100755 index 000000000..a94835be3 --- /dev/null +++ b/books/kochanowski_piesn2_XXII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XXII (2) Proszę jeśli się z tobą co śpiewało +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XXIII.xml b/books/kochanowski_piesn2_XXIII.xml new file mode 100755 index 000000000..7ae251eec --- /dev/null +++ b/books/kochanowski_piesn2_XXIII.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XXIII (2) Nie zawżdy piękna Zofija +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XXIV.xml b/books/kochanowski_piesn2_XXIV.xml new file mode 100755 index 000000000..3c8521864 --- /dev/null +++ b/books/kochanowski_piesn2_XXIV.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśń XXIV (2) Niezwykłym i nie leda piórem opatrzony +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_piesn2_XXV.xml b/books/kochanowski_piesn2_XXV.xml new file mode 100755 index 000000000..1ccc85e3a --- /dev/null +++ b/books/kochanowski_piesn2_XXV.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Pieśń XXV (2) Czego chcesz od nas Panie +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +G +L +pol + + + diff --git a/books/kochanowski_piesn_swietojanska.xml b/books/kochanowski_piesn_swietojanska.xml new file mode 100755 index 000000000..563ef8fbc --- /dev/null +++ b/books/kochanowski_piesn_swietojanska.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Pieśń świętojańska o sobótce +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Pie%C5%9B%C5%84+%C5%9Bwi%C4%99toja%C5%84ska+o+sob%C3%B3tce +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +G +L +pol + + + diff --git a/books/kochanowski_piesni_dedykacja.xml b/books/kochanowski_piesni_dedykacja.xml new file mode 100755 index 000000000..1f48e1a93 --- /dev/null +++ b/books/kochanowski_piesni_dedykacja.xml @@ -0,0 +1,29 @@ + + + +Kochanowski, Jan +Pieśni - Dedykacja +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Pieśń +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Pie%C5%9Bni+-+Dedykacja +http://www.polona.pl/Content/1499 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 1, oprac. Julian Krzyżanowski, wyd. 8, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/kochanowski_tren_1.xml b/books/kochanowski_tren_1.xml new file mode 100755 index 000000000..2e684e157 --- /dev/null +++ b/books/kochanowski_tren_1.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren I (Wszytki płacze wszytki łzy) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_10.xml b/books/kochanowski_tren_10.xml new file mode 100755 index 000000000..84dd50885 --- /dev/null +++ b/books/kochanowski_tren_10.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren X (Orszulo moja wdzięczna) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_11.xml b/books/kochanowski_tren_11.xml new file mode 100755 index 000000000..f46f1806a --- /dev/null +++ b/books/kochanowski_tren_11.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren XI (Fraszka cnota!) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_12.xml b/books/kochanowski_tren_12.xml new file mode 100755 index 000000000..d411b59e6 --- /dev/null +++ b/books/kochanowski_tren_12.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren XII (Å»aden ojciec podobno barziej nie miłował) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_13.xml b/books/kochanowski_tren_13.xml new file mode 100755 index 000000000..f446d0334 --- /dev/null +++ b/books/kochanowski_tren_13.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren XIII (Moja wdzięczna Orszulo) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_14.xml b/books/kochanowski_tren_14.xml new file mode 100755 index 000000000..7f6d8172b --- /dev/null +++ b/books/kochanowski_tren_14.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren XIV (Gdzie te wrota nieszczęsne) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_15.xml b/books/kochanowski_tren_15.xml new file mode 100755 index 000000000..0992a05a3 --- /dev/null +++ b/books/kochanowski_tren_15.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren XV (Erato złotowłosa i ty) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_16.xml b/books/kochanowski_tren_16.xml new file mode 100755 index 000000000..1ff10b152 --- /dev/null +++ b/books/kochanowski_tren_16.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren XVI (Nieszczęściu k'woli) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_17.xml b/books/kochanowski_tren_17.xml new file mode 100755 index 000000000..c6810e8d8 --- /dev/null +++ b/books/kochanowski_tren_17.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren XVII (Pańska ręka mię dotknęła) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_18.xml b/books/kochanowski_tren_18.xml new file mode 100755 index 000000000..4ef6b0f33 --- /dev/null +++ b/books/kochanowski_tren_18.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren VIII (My nieposłuszne Panie dzieci Twoje) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_19_albo_sen.xml b/books/kochanowski_tren_19_albo_sen.xml new file mode 100755 index 000000000..19a1b9459 --- /dev/null +++ b/books/kochanowski_tren_19_albo_sen.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren XIX albo Sen +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_2.xml b/books/kochanowski_tren_2.xml new file mode 100755 index 000000000..9bed641ee --- /dev/null +++ b/books/kochanowski_tren_2.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren II (Jeślim kiedy nad dziećmi) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_3.xml b/books/kochanowski_tren_3.xml new file mode 100755 index 000000000..61e884fef --- /dev/null +++ b/books/kochanowski_tren_3.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren III (Wzgardziłaś mną dziedziczko) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_4.xml b/books/kochanowski_tren_4.xml new file mode 100755 index 000000000..eacd8bd35 --- /dev/null +++ b/books/kochanowski_tren_4.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren IV (Zgwałciłaś niepobożna Śmierci) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_5.xml b/books/kochanowski_tren_5.xml new file mode 100755 index 000000000..0720f6e46 --- /dev/null +++ b/books/kochanowski_tren_5.xml @@ -0,0 +1,31 @@ + + + +Kochanowski, Jan +Tren V (Jako oliwka mała) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +G +L +pol + + + diff --git a/books/kochanowski_tren_6.xml b/books/kochanowski_tren_6.xml new file mode 100755 index 000000000..7ab9878eb --- /dev/null +++ b/books/kochanowski_tren_6.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren VI (Ucieszna moja śpiewaczko!) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_7.xml b/books/kochanowski_tren_7.xml new file mode 100755 index 000000000..ab67cc85d --- /dev/null +++ b/books/kochanowski_tren_7.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren VII (Nieszczęsne ochędóstwo) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_tren_8.xml b/books/kochanowski_tren_8.xml new file mode 100755 index 000000000..e186cbcd7 --- /dev/null +++ b/books/kochanowski_tren_8.xml @@ -0,0 +1,31 @@ + + + +Kochanowski, Jan +Tren VIII (Wielkieś mi uczyniła pustki) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +G +L +pol + + + diff --git a/books/kochanowski_tren_9.xml b/books/kochanowski_tren_9.xml new file mode 100755 index 000000000..9c5759caa --- /dev/null +++ b/books/kochanowski_tren_9.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Tren IX (Kupić by cię Mądrości) +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_treny_epitafium_hannie_kochanowskiej.xml b/books/kochanowski_treny_epitafium_hannie_kochanowskiej.xml new file mode 100755 index 000000000..b42c1e4f8 --- /dev/null +++ b/books/kochanowski_treny_epitafium_hannie_kochanowskiej.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Treny - Epitafium +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Treny+-+Epitafium +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/kochanowski_treny_motto_i_dedykacja.xml b/books/kochanowski_treny_motto_i_dedykacja.xml new file mode 100755 index 000000000..98b9dc2ce --- /dev/null +++ b/books/kochanowski_treny_motto_i_dedykacja.xml @@ -0,0 +1,30 @@ + + + +Kochanowski, Jan +Treny - Dedykacja +Treny +Sekuła, Aleksandra +Krzyżanowski, Julian +Otwinowska, Barbara +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Renesans +Liryka +Tren +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Treny+-+Dedykacja +http://www.polona.pl/Content/1501 +Kochanowski, Jan (1530-1584), Dzieła polskie, tom 2, Państwowy Instytut Wydawniczy, wyd. 8, Warszawa, 1976 +Domena publiczna - Jan Kochanowski zm. 1584 +1584 +xml +text +text +2007-08-30 +L +pol + + + diff --git a/books/konopnicka_nasza_szkapa.xml b/books/konopnicka_nasza_szkapa.xml new file mode 100755 index 000000000..fb8026e04 --- /dev/null +++ b/books/konopnicka_nasza_szkapa.xml @@ -0,0 +1,28 @@ + + + +Konopnicka, Maria +Nasza szkapa +Sekuła, Aleksandra +Sutkowska, Olga +Jurewicz, Kamil +Fundacja Nowoczesna Polska +Pozytywizm +Epika +Nowela +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Nasza+szkapa +http://www.polona.pl/Content/6012 +Maria Konopnicka, Nasza szkapa, Gebethner i Wolf, wyd. 3, Warszawa, 1913 +Domena publiczna - Maria Konopnicka zm. 1910 +1910 +xml +text +text +2008-06-10 +SP2 +pol + + + diff --git a/books/mickiewicz_do_m.xml b/books/mickiewicz_do_m.xml new file mode 100755 index 000000000..633bb5445 --- /dev/null +++ b/books/mickiewicz_do_m.xml @@ -0,0 +1,29 @@ + + + +Mickiewicz, Adam +Do M*** +Sekuła, Aleksandra +Kallenbach, Józef +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Do+M%2A%2A%2A +http://www.polona.pl/Content/2222 +Mickiewicz, Adam (1798-1855), Poezje, tom 1 (Wiersze młodzieńcze - Ballady i romanse - Wiersze do r. 1824), Krakowska Spółdzielnia Wydawnicza, wyd. 2 zwiększone, Kraków, 1922 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-09-06 +G +L +pol + + + diff --git a/books/mickiewicz_lilije.xml b/books/mickiewicz_lilije.xml new file mode 100755 index 000000000..1fea8a6e6 --- /dev/null +++ b/books/mickiewicz_lilije.xml @@ -0,0 +1,31 @@ + + + +Mickiewicz, Adam +Lilie +Ballady i romanse +Sekuła, Aleksandra +Kallenbach, Józef +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Ballada +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Lilie +http://www.polona.pl/Content/2222 +Mickiewicz, Adam (1798-1855), Poezje, tom 1 (Wiersze młodzieńcze - Ballady i romanse - Wiersze do r. 1824), Krakowska Spółdzielnia Wydawnicza, wyd. 2 zwiększone, Kraków, 1922 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-09-06 +SP2 +G +L +pol + + + diff --git a/books/mickiewicz_oda_do_mlodosci.xml b/books/mickiewicz_oda_do_mlodosci.xml new file mode 100755 index 000000000..cec6e5a6c --- /dev/null +++ b/books/mickiewicz_oda_do_mlodosci.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Oda do młodości +Sekuła, Aleksandra +Pigoń, Stanisław +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Oda +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Oda+do+m%C5%82odo%C5%9Bci +http://www.polona.pl/Content/2624 +Mickiewicz, Adam (1798-1855), Poezje, tom 1, Gubrynowicz, Lwów, 1929 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/mickiewicz_pani_twardowska.xml b/books/mickiewicz_pani_twardowska.xml new file mode 100755 index 000000000..ebb9eca05 --- /dev/null +++ b/books/mickiewicz_pani_twardowska.xml @@ -0,0 +1,29 @@ + + + +Mickiewicz, Adam +Pani Twardowska +Ballady i romanse +Sekuła, Aleksandra +Kallenbach, Józef +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Ballada +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Pani+Twardowska +http://www.polona.pl/Content/2222 +Mickiewicz, Adam (1798-1855), Poezje, tom 1 (Wiersze młodzieńcze - Ballady i romanse - Wiersze do r. 1824), Krakowska Spółdzielnia Wydawnicza, wyd. 2 zwiększone, Kraków, 1922 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-09-06 +SP2 +pol + + + diff --git a/books/mickiewicz_powrot_taty.xml b/books/mickiewicz_powrot_taty.xml new file mode 100755 index 000000000..d6e4ff581 --- /dev/null +++ b/books/mickiewicz_powrot_taty.xml @@ -0,0 +1,29 @@ + + + +Mickiewicz, Adam +Powrót taty +Ballady i romanse +Sekuła, Aleksandra +Kallenbach, Józef +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Ballada +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Powr%C3%B3t+taty +http://www.polona.pl/Content/2222 +Mickiewicz, Adam (1798-1855), Poezje, tom 1 (Wiersze młodzieńcze - Ballady i romanse - Wiersze do r. 1824), Krakowska Spółdzielnia Wydawnicza, wyd. 2 zwiększone, Kraków, 1922 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-09-06 +SP2 +pol + + + diff --git a/books/mickiewicz_reduta_ordona.xml b/books/mickiewicz_reduta_ordona.xml new file mode 100755 index 000000000..01f832dc4 --- /dev/null +++ b/books/mickiewicz_reduta_ordona.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Reduta Ordona +Sekuła, Aleksandra +Bystrzycki, Jan +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Reduta+Ordona +http://www.polona.pl/dlibra/doccontent2?id=2223&from=&from=generalsearch&dirids=1&lang=pl +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., W. L. Anczyc, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-12-20 +G +pol + + + diff --git a/books/mickiewicz_rekawiczka.xml b/books/mickiewicz_rekawiczka.xml new file mode 100755 index 000000000..53d0e1817 --- /dev/null +++ b/books/mickiewicz_rekawiczka.xml @@ -0,0 +1,31 @@ + + + +Mickiewicz, Adam +Rękawiczka +Ballady i romanse +Sekuła, Aleksandra +Kallenbach, Józef +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Ballada +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/R%C4%99kawiczka +http://www.polona.pl/Content/2222 +Mickiewicz, Adam (1798-1855), Poezje, tom 1 (Wiersze młodzieńcze - Ballady i romanse - Wiersze do r. 1824), Krakowska Spółdzielnia Wydawnicza, wyd. 2 zwiększone, Kraków, 1922 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-09-06 +SP2 +G +L +pol + + + diff --git a/books/mickiewicz_romantycznosc.xml b/books/mickiewicz_romantycznosc.xml new file mode 100755 index 000000000..a24c7427a --- /dev/null +++ b/books/mickiewicz_romantycznosc.xml @@ -0,0 +1,31 @@ + + + +Mickiewicz, Adam +Romantyczność +Ballady i romanse +Sekuła, Aleksandra +Kallenbach, Józef +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Ballada +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Romantyczno%C5%9B%C4%87 +http://www.polona.pl/Content/2222 +Mickiewicz, Adam (1798-1855), Poezje, tom 1 (Wiersze młodzieńcze - Ballady i romanse - Wiersze do r. 1824), Krakowska Spółdzielnia Wydawnicza, wyd. 2 zwiększone, Kraków, 1922 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-09-06 +SP2 +G +L +pol + + + diff --git a/books/mickiewicz_rybka.xml b/books/mickiewicz_rybka.xml new file mode 100755 index 000000000..b59f3d9a8 --- /dev/null +++ b/books/mickiewicz_rybka.xml @@ -0,0 +1,31 @@ + + + +Mickiewicz, Adam +Rybka +Ballady i romanse +Sekuła, Aleksandra +Kallenbach, Józef +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Ballada +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Rybka +http://www.polona.pl/Content/2222 +Mickiewicz, Adam (1798-1855), Poezje, tom 1 (Wiersze młodzieńcze - Ballady i romanse - Wiersze do r. 1824), Krakowska Spółdzielnia Wydawnicza, wyd. 2 zwiększone, Kraków, 1922 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-09-06 +SP2 +G +L +pol + + + diff --git a/books/mickiewicz_smierc_pulkownika.xml b/books/mickiewicz_smierc_pulkownika.xml new file mode 100755 index 000000000..0713a020d --- /dev/null +++ b/books/mickiewicz_smierc_pulkownika.xml @@ -0,0 +1,28 @@ + + + +Mickiewicz, Adam +Śmierć Pułkownika +Sekuła, Alaksandra +Bystrzycki, Jan +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/%C5%9Amier%C4%87+Pu%C5%82kownika +http://www.polona.pl/dlibra/doccontent2?id=2223&from=&from=generalsearch&dirids=1&lang=pl +Mickiewicz, Adam (1798-1855), Poezje, tom 2, Wiersze z lat 1825-1855 (Pieśni - Sonety - Poezje patrjotyczne, religijne i filozoficzne - Wiersze okolicznościowe - Bajki), Krakowska Spółdzielnia Wydawnicza, wyd. 2 popr., W. L. Anczyc, Kraków, 1928 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-12-20 +L +pol + + + diff --git a/books/mickiewicz_switez.xml b/books/mickiewicz_switez.xml new file mode 100755 index 000000000..22c853695 --- /dev/null +++ b/books/mickiewicz_switez.xml @@ -0,0 +1,31 @@ + + + +Mickiewicz, Adam +Świteź +Ballady i romanse +Sekuła, Aleksandra +Kallenbach, Józef +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Ballada +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/%C5%9Awite%C5%BA +http://www.polona.pl/Content/2222 +Mickiewicz, Adam (1798-1855), Poezje, tom 1 (Wiersze młodzieńcze - Ballady i romanse - Wiersze do r. 1824), Krakowska Spółdzielnia Wydawnicza, wyd. 2 zwiększone, Kraków, 1922 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-09-06 +SP2 +G +L +pol + + + diff --git a/books/mickiewicz_switezianka.xml b/books/mickiewicz_switezianka.xml new file mode 100755 index 000000000..871f953b9 --- /dev/null +++ b/books/mickiewicz_switezianka.xml @@ -0,0 +1,31 @@ + + + +Mickiewicz, Adam +Świtezianka +Ballady i romanse +Sekuła, Aleksandra +Kallenbach, Józef +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Ballada +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/%C5%9Awitezianka +http://www.polona.pl/Content/2222 +Mickiewicz, Adam (1798-1855), Poezje, tom 1 (Wiersze młodzieńcze - Ballady i romanse - Wiersze do r. 1824), Krakowska Spółdzielnia Wydawnicza, wyd. 2 zwiększone, Kraków, 1922 +Domena publiczna - Adam Mickiewicz zm. 1855 +1855 +xml +text +text +2007-09-06 +SP2 +G +L +pol + + + diff --git a/books/morsztyn_cuda_milosci_1.xml b/books/morsztyn_cuda_milosci_1.xml new file mode 100755 index 000000000..f9aeaa79c --- /dev/null +++ b/books/morsztyn_cuda_milosci_1.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Cuda miłości (Karmię frasunkiem miłość) +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/morsztyn_cuda_milosci_2.xml b/books/morsztyn_cuda_milosci_2.xml new file mode 100755 index 000000000..27ba5af43 --- /dev/null +++ b/books/morsztyn_cuda_milosci_2.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Cuda miłości (Przebóg! Jak żyję) +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/morsztyn_do_motyla.xml b/books/morsztyn_do_motyla.xml new file mode 100755 index 000000000..5ea0090ea --- /dev/null +++ b/books/morsztyn_do_motyla.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Do motyla +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Do+motyla +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/morsztyn_do_swoich_ksiazek_1.xml b/books/morsztyn_do_swoich_ksiazek_1.xml new file mode 100755 index 000000000..dbd07a25e --- /dev/null +++ b/books/morsztyn_do_swoich_ksiazek_1.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Do swoich książek (Dokąd się moja lutni) +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/morsztyn_do_swoich_ksiazek_2.xml b/books/morsztyn_do_swoich_ksiazek_2.xml new file mode 100755 index 000000000..622f41e93 --- /dev/null +++ b/books/morsztyn_do_swoich_ksiazek_2.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Do swoich książek (Hola! już dosyć) +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/morsztyn_do_trupa.xml b/books/morsztyn_do_trupa.xml new file mode 100755 index 000000000..89f072b77 --- /dev/null +++ b/books/morsztyn_do_trupa.xml @@ -0,0 +1,29 @@ + + + +Morsztyn, Jan Andrzej +Do trupa +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Do+trupa +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +G +L +pol + + + diff --git a/books/morsztyn_na_krzyzyk_na_piersiach_jednej_panny.xml b/books/morsztyn_na_krzyzyk_na_piersiach_jednej_panny.xml new file mode 100755 index 000000000..53387c083 --- /dev/null +++ b/books/morsztyn_na_krzyzyk_na_piersiach_jednej_panny.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Na krzyżyk na piersiach jednej panny +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Sonet +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Na+krzy%C5%BCyk+na+piersiach+jednej+panny +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/morsztyn_na_zegar_ciekacy.xml b/books/morsztyn_na_zegar_ciekacy.xml new file mode 100755 index 000000000..403815a5b --- /dev/null +++ b/books/morsztyn_na_zegar_ciekacy.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Na zegarek ciekący +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Epigramat +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Na+zegarek+ciek%C4%85cy +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/morsztyn_nadgrobek_perlisi.xml b/books/morsztyn_nadgrobek_perlisi.xml new file mode 100755 index 000000000..ee2dec7f4 --- /dev/null +++ b/books/morsztyn_nadgrobek_perlisi.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Nadgrobek Perlisi +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Nadgrobek+Perlisi +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/morsztyn_niestatek_1.xml b/books/morsztyn_niestatek_1.xml new file mode 100755 index 000000000..4f0d56e92 --- /dev/null +++ b/books/morsztyn_niestatek_1.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Niestatek (Oczy są ogień) +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Epigramat +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/morsztyn_niestatek_2.xml b/books/morsztyn_niestatek_2.xml new file mode 100755 index 000000000..e3406f3b1 --- /dev/null +++ b/books/morsztyn_niestatek_2.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Niestatek (Prędzej kto wiatr w wór zamknie) +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Epigramat +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. + +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/morsztyn_pszczola_w_bursztynie.xml b/books/morsztyn_pszczola_w_bursztynie.xml new file mode 100755 index 000000000..c05e51c30 --- /dev/null +++ b/books/morsztyn_pszczola_w_bursztynie.xml @@ -0,0 +1,28 @@ + + + +Morsztyn, Jan Andrzej +Pszczoła w bursztynie +Sekuła, Aleksandra +Kukulski, Leszek +Sutkowska, Olga +Fundacja Nowoczesna Polska +Barok +Liryka +Epigramat +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Pszczo%C5%82a+w+bursztynie +http://www.polona.pl/Content/5265 +Morsztyn, Jan Andrzej (1621-1693), 275 wierszy, Państwowy Instytut Wydawniczy, Warszawa, 1977 +Domena publiczna - Jan Andrzej Morsztyn zm. 1693 +1693 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/oppman_biala_dama.xml b/books/oppman_biala_dama.xml new file mode 100755 index 000000000..4705cce29 --- /dev/null +++ b/books/oppman_biala_dama.xml @@ -0,0 +1,28 @@ + + + +Oppman, Artur +Biała Dama +Legendy warszawskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Legenda +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Bia%C5%82a+DamaL +http://www.polona.pl/Content/799 +Oppman, Artur (1867-1931), Legendy warszawskie, Księgarnia św. Wojciecha, Poznań, Warszawa [etc.], 1925 +Domena publiczna - Artur Oppman zm. 1931 +1931 +xml +text +text +2007-08-30 +SP2 +pol + + + diff --git a/books/oppman_chrystus_cudowny_u_fary.xml b/books/oppman_chrystus_cudowny_u_fary.xml new file mode 100755 index 000000000..ce87d5814 --- /dev/null +++ b/books/oppman_chrystus_cudowny_u_fary.xml @@ -0,0 +1,28 @@ + + + +Oppman, Artur +Chrystus Cudowny u Fary +Legendy warszawskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Legenda +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Chrystus+Cudowny+u+Fary +http://www.polona.pl/Content/799 +Oppman, Artur (1867-1931), Legendy warszawskie, Księgarnia św. Wojciecha, Poznań, Warszawa [etc.], 1925 +Domena publiczna - Artur Oppman zm. 1931 +1931 +xml +text +text +2007-08-30 +SP2 +pol + + + diff --git a/books/oppman_kosciol_panny_marii.xml b/books/oppman_kosciol_panny_marii.xml new file mode 100755 index 000000000..182ea875b --- /dev/null +++ b/books/oppman_kosciol_panny_marii.xml @@ -0,0 +1,28 @@ + + + +Oppman, Artur +Kościół Panny Marii +Legendy warszawskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Legenda +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Ko%C5%9Bci%C3%B3%C5%82+Panny+Marii +http://www.polona.pl/Content/799 +Oppman, Artur (1867-1931), Legendy warszawskie, Księgarnia św. Wojciecha, Poznań, Warszawa [etc.], 1925 +Domena publiczna - Artur Oppman zm. 1931 +1931 +xml +text +text +2007-08-30 +SP2 +pol + + + diff --git a/books/oppman_legendy_warszawskie_bazyliszek.xml b/books/oppman_legendy_warszawskie_bazyliszek.xml new file mode 100755 index 000000000..6a46606c1 --- /dev/null +++ b/books/oppman_legendy_warszawskie_bazyliszek.xml @@ -0,0 +1,28 @@ + + + +Oppman, Artur +Bazyliszek +Legendy warszawskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Legenda +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Bazyliszek +http://www.polona.pl/Content/799 +Oppman, Artur (1867-1931), Legendy warszawskie, Księgarnia św. Wojciecha, Poznań, Warszawa [etc.], 1925 +Domena publiczna - Artur Oppman zm. 1931 +1931 +xml +text +text +2007-08-30 +SP2 +pol + + + diff --git a/books/oppman_syrena.xml b/books/oppman_syrena.xml new file mode 100755 index 000000000..8bf4d0e0a --- /dev/null +++ b/books/oppman_syrena.xml @@ -0,0 +1,28 @@ + + + +Oppman, Artur +Syrena +Legendy warszawskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Legenda +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Syrena +http://www.polona.pl/Content/799 +Oppman, Artur (1867-1931), Legendy warszawskie, Księgarnia św. Wojciecha, Poznań, Warszawa [etc.], 1925 +Domena publiczna - Artur Oppman zm. 1931 +1931 +xml +text +text +2007-08-30 +SP2 +pol + + + diff --git a/books/oppman_wstep.xml b/books/oppman_wstep.xml new file mode 100755 index 000000000..af8405326 --- /dev/null +++ b/books/oppman_wstep.xml @@ -0,0 +1,28 @@ + + + +Oppman, Artur +Wstęp +Legendy warszawskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Legenda +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Wst%C4%99p +http://www.polona.pl/Content/799 +Oppman, Artur (1867-1931), Legendy warszawskie, Księgarnia św. Wojciecha, Poznań, Warszawa [etc.], 1925 +Domena publiczna - Artur Oppman zm. 1931 +1931 +xml +text +text +2007-08-30 +SP2 +pol + + + diff --git a/books/oppman_zbojcy.xml b/books/oppman_zbojcy.xml new file mode 100755 index 000000000..7bf1e6939 --- /dev/null +++ b/books/oppman_zbojcy.xml @@ -0,0 +1,28 @@ + + + +Oppman, Artur +Zbójcy +Legendy warszawskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Legenda +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Zb%C3%B3jcy +http://www.polona.pl/Content/799 +Oppman, Artur (1867-1931), Legendy warszawskie, Księgarnia św. Wojciecha, Poznań, Warszawa [etc.], 1925 +Domena publiczna - Artur Oppman zm. 1931 +1931 +xml +text +text +2007-08-30 +SP2 +pol + + + diff --git a/books/oppman_zlota_kaczka.xml b/books/oppman_zlota_kaczka.xml new file mode 100755 index 000000000..20a184501 --- /dev/null +++ b/books/oppman_zlota_kaczka.xml @@ -0,0 +1,28 @@ + + + +Oppman, Artur +Złota kaczka +Legendy warszawskie +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Legenda +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Z%C5%82ota+kaczka +http://www.polona.pl/Content/799 +Oppman, Artur (1867-1931), Legendy warszawskie, Księgarnia św. Wojciecha, Poznań, Warszawa [etc.], 1925 +Domena publiczna - Artur Oppman zm. 1931 +1931 +xml +text +text +2007-08-30 +SP2 +pol + + + diff --git a/books/reymont_chlopi_jesien.xml b/books/reymont_chlopi_jesien.xml new file mode 100755 index 000000000..3b619adfc --- /dev/null +++ b/books/reymont_chlopi_jesien.xml @@ -0,0 +1,29 @@ + + + +Reymont, Władysław Stanisław +Chłopi - Jesień +Sekuła, Aleksandra +Jodełka-Burzecki, Tomasz +Orlewiczowa, Irena +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Powieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/Content/4072 +Reymont, Władysław Stanisław (1867-1925), Chłopi, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Władysław St. Reymont zm. 1925 +1925 +xml +text +text +2008-04-07 +L +pol + + + diff --git a/books/sienkiewicz_janko_muzykant.xml b/books/sienkiewicz_janko_muzykant.xml new file mode 100755 index 000000000..d72468e05 --- /dev/null +++ b/books/sienkiewicz_janko_muzykant.xml @@ -0,0 +1,27 @@ + + + +Sienkiewicz, Henryk +Janko Muzykant +Sekuła, Aleksandra +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Pozytywizm +Epika +Nowela +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Janko+Muzykant +http://www.polona.pl/dlibra/doccontent2?id=3751&from=editionindex&dirids=4 +Sienkiewicz, Henryk (1846-1916), Pisma wybrane. Nowele, tom 1, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Henryk Sienkiewicz zm. 1916 +1916 +xml +text +text +2007-08-30 +SP2 +pol + + + diff --git a/books/sienkiewicz_latarnik.xml b/books/sienkiewicz_latarnik.xml new file mode 100755 index 000000000..ebe9652b0 --- /dev/null +++ b/books/sienkiewicz_latarnik.xml @@ -0,0 +1,28 @@ + + + +Sienkiewicz, Henryk +Latarnik +Sekuła, Aleksandra +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Pozytywizm +Epika +Nowela +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Latarnik +http://www.polona.pl/dlibra/doccontent2?id=3752&from=editionindex&dirids=4 +Sienkiewicz, Henryk (1846-1916), Pisma wybrane. Nowele, tom 2, Państwowy Instytut Wydawniczy, Warszawa, 1976 +Domena publiczna - Henryk Sienkiewicz zm. 1916 +1916 +xml +text +text +2007-08-30 +SP2 +G +pol + + + diff --git a/books/slowacki_do_matki.xml b/books/slowacki_do_matki.xml new file mode 100755 index 000000000..3be4dce75 --- /dev/null +++ b/books/slowacki_do_matki.xml @@ -0,0 +1,26 @@ + + + +Słowacki, Juliusz +Do matki +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Do+matki +http://www.polona.pl/Content/4060 +Mazanowski, Antoni (1858-1916), Wypisy polskie na VII klasę gimnazyalną, [s.n.], Kraków, 1914 +Domena publiczna - Juliusz Słowacki zm. 1849 +1849 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/slowacki_grob_agamemnona.xml b/books/slowacki_grob_agamemnona.xml new file mode 100755 index 000000000..b0047c06d --- /dev/null +++ b/books/slowacki_grob_agamemnona.xml @@ -0,0 +1,27 @@ + + + +Słowacki, Juliusz +Grób Agamemnona +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Gr%C3%B3b+Agamemnona +http://www.polona.pl/dlibra/doccontent2?id=5175&from=editionindex&dirids=4 +Słowacki, Juliusz (1809-1849), Pisma Juliusza Słowackiego, tom 3, Lwów, 1925 +Domena publiczna - Juliusz Słowacki zm. 1849 +1849 +xml +text +text +2008-01-25 +L +pol + + + diff --git a/books/slowacki_hymn.xml b/books/slowacki_hymn.xml new file mode 100755 index 000000000..1c037fa48 --- /dev/null +++ b/books/slowacki_hymn.xml @@ -0,0 +1,28 @@ + + + +Słowacki, Juliusz +Hymn +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Hymn +http://www.polona.pl/Content/4060 +Mazanowski, Antoni (1858-1916), Wypisy polskie na VII klasę gimnazyalną, [s.n.], Kraków, 1914 +Domena publiczna - Juliusz Słowacki zm. 1849 +1849 +xml +text +text +2007-09-06 +G +L +pol + + + diff --git a/books/slowacki_odpowiedz_na_psalmy_przyszlosci.xml b/books/slowacki_odpowiedz_na_psalmy_przyszlosci.xml new file mode 100755 index 000000000..ed39178a9 --- /dev/null +++ b/books/slowacki_odpowiedz_na_psalmy_przyszlosci.xml @@ -0,0 +1,27 @@ + + + +Słowacki, Juliusz +Odpowiedź na "Psalmy przyszłości" +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Odpowied%C5%BA+na+%22Psalmy+przysz%C5%82o%C5%9Bci%22 +http://www.polona.pl/Content/4060 +Mazanowski, Antoni (1858-1916), Wypisy polskie na VII klasę gimnazyalną, [s.n.], Kraków, 1914 +Domena publiczna - Juliusz Słowacki zm. 1849 +1849 +xml +text +text +2007-09-06 +L +pol + + + diff --git a/books/slowacki_testament_moj.xml b/books/slowacki_testament_moj.xml new file mode 100755 index 000000000..d94741d31 --- /dev/null +++ b/books/slowacki_testament_moj.xml @@ -0,0 +1,28 @@ + + + +Słowacki, Juliusz +Testament mój +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Testament+m%C3%B3j +http://www.polona.pl/Content/4060 +Mazanowski, Antoni (1858-1916), Wypisy polskie na VII klasę gimnazyalną, [s.n.], Kraków, 1914 +Domena publiczna - Juliusz Słowacki zm. 1849 +1849 +xml +text +text +2007-09-06 +G +L +pol + + + diff --git a/books/slowacki_w_pamietniku_zofii_bobrowny.xml b/books/slowacki_w_pamietniku_zofii_bobrowny.xml new file mode 100755 index 000000000..53da69d06 --- /dev/null +++ b/books/slowacki_w_pamietniku_zofii_bobrowny.xml @@ -0,0 +1,28 @@ + + + +Słowacki, Juliusz +W pamiętniku Zofii Bobrówny +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Romantyzm +Liryka +Wiersz +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/W+pami%C4%99tniku+Zofii+Bobr%C3%B3wny +http://www.polona.pl/Content/4060 +Mazanowski, Antoni (1858-1916), Wypisy polskie na VII klasę gimnazyalną, [s.n.], Kraków, 1914 +Domena publiczna - Juliusz Słowacki zm. 1849 +1849 +xml +text +text +2007-09-06 +SP2 +L +pol + + + diff --git a/books/sofokles_antygona.xml b/books/sofokles_antygona.xml new file mode 100755 index 000000000..66dc3b0e8 --- /dev/null +++ b/books/sofokles_antygona.xml @@ -0,0 +1,28 @@ + + + +Sofokles +Antygona +Sekuła, Aleksandra +Morawski, Kazimierz +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Starożytność +Dramat +Tragedia +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Antygona +http://www.polona.pl/Content/3768 +Sofokles (496-406 a.C.), Antygona, Zakład Narodowy im. Ossolińskich, wyd. 7, Lwów, 1939 +Domena publiczna - tłumacz Kazimierz Morawski zm. 1925 +1925 +xml +text +text +2007-08-30 +G +pol + + + diff --git a/books/sofokles_krol_edyp.xml b/books/sofokles_krol_edyp.xml new file mode 100755 index 000000000..070c69f74 --- /dev/null +++ b/books/sofokles_krol_edyp.xml @@ -0,0 +1,28 @@ + + + +Sofokles +Król Edyp +Sekuła, Aleksandra +Morawski, Kazimierz +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Starożytność +Dramat +Tragedia +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Kr%C3%B3l+Edyp +http://www.polona.pl/Content/3067 +Sofokles (496-406 a.C.), Król Edyp, Zakład Narodowy im. Ossolińskich, wyd. 2, Kraków, 1947 +Domena publiczna - tłumacz Kazimierz Morawski zm. 1925 +1925 +xml +text +text +2007-08-31 +L +pol + + + diff --git a/books/zeromski_doktor_piotr.xml b/books/zeromski_doktor_piotr.xml new file mode 100755 index 000000000..179a3900d --- /dev/null +++ b/books/zeromski_doktor_piotr.xml @@ -0,0 +1,28 @@ + + + +Å»eromski, Stefan +Doktor Piotr +Pigoń, Stanisław +Sekuła, Aleksandra +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Modernizm +Epika +Nowela +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Doktor+Piotr +http://www.polona.pl/dlibra/doccontent2?id=3343&from=editionindex&dirids=4 +Å»eromski, Stefan (1864-1925), Opowiadania. Utwory powieściowe, Czytelnik, wyd. 5, Warszawa, 1973 +Domena publiczna - Stefan Å»eromski zm. 1925 +1925 +xml +text +text +2007-08-31 +G +pol + + + diff --git a/books/zeromski_ludzie_bezdomni_tom_drugi.xml b/books/zeromski_ludzie_bezdomni_tom_drugi.xml new file mode 100755 index 000000000..e7784bf41 --- /dev/null +++ b/books/zeromski_ludzie_bezdomni_tom_drugi.xml @@ -0,0 +1,28 @@ + + + +Å»eromski, Stefan +Ludzie bezdomni - tom 2 +Ludzie bezdomni +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Powieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=4134&from=editionindex&dirids=1 +Å»eromski, Stefan (1864-1925), Ludzie bezdomni, Czytelnik, wyd. 24, Warszawa, 1976 +Domena publiczna: Stefan Å»eromski zm. 1925 +1925 +xml +text +text +2007-11-10 +L +pol + + + diff --git a/books/zeromski_ludzie_bezdomni_tom_pierwszy.xml b/books/zeromski_ludzie_bezdomni_tom_pierwszy.xml new file mode 100755 index 000000000..b689e3583 --- /dev/null +++ b/books/zeromski_ludzie_bezdomni_tom_pierwszy.xml @@ -0,0 +1,28 @@ + + + +Å»eromski, Stefan +Ludzie bezdomni - tom 1 +Ludzie bezdomni +Sekuła, Aleksandra +Sutkowska, Olga +Fundacja Nowoczesna Polska +Modernizm +Epika +Powieść +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +LINK DO STRONY W SERWISIE WOLNELEKTURY.PL +http://www.polona.pl/dlibra/doccontent2?id=4134&from=editionindex&dirids=1 +Å»eromski, Stefan (1864-1925), Ludzie bezdomni, Czytelnik, wyd. 24, Warszawa, 1976 +Domena publiczna: Stefan Å»eromski zm. 1925 +1925 +xml +text +text +2007-11-10 +L +pol + + + diff --git a/books/zeromski_silaczka.xml b/books/zeromski_silaczka.xml new file mode 100755 index 000000000..a6bd4854d --- /dev/null +++ b/books/zeromski_silaczka.xml @@ -0,0 +1,28 @@ + + + +Å»eromski, Stefan +Siłaczka +Pigoń, Stanisław +Sekuła, Aleksandra +Gałecki, Dariusz +Fundacja Nowoczesna Polska +Modernizm +Epika +Nowela +Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Partnerem projektu jest Prokom Software SA. Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. +http://www.wolnelektury.pl/lektura/Si%C5%82aczka +http://www.polona.pl/Content/3343 +Å»eromski, Stefan (1864-1925), Opowiadania. Utwory powieściowe, Czytelnik, wyd. 5, Warszawa, 1973 +Domena publiczna - Stefan Å»eromski zm. 1925 +1925 +xml +text +text +2007-08-31 +G +pol + + + diff --git a/catalogue/.DS_Store b/catalogue/.DS_Store new file mode 100644 index 000000000..549fcd833 Binary files /dev/null and b/catalogue/.DS_Store differ diff --git a/catalogue/__init__.py b/catalogue/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/catalogue/admin.py b/catalogue/admin.py new file mode 100644 index 000000000..2afc794be --- /dev/null +++ b/catalogue/admin.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +from django.contrib import admin +from django import forms +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext_lazy as _ + +from newtagging.admin import TaggableModelAdmin +from catalogue.models import Book, Tag + + +class TagAdmin(admin.ModelAdmin): + list_display = ('name', 'slug', 'sort_key', 'category', 'has_description',) + list_filter = ('category',) + search_fields = ('name',) + ordering = ('name',) + + prepopulated_fields = {'slug': ('name',), 'sort_key': ('name',),} + radio_fields = {'category': admin.HORIZONTAL} + +admin.site.register(Tag, TagAdmin) + + +class BookAdmin(TaggableModelAdmin): + tag_model = Tag + + list_display = ('title', 'slug', 'has_pdf_file', 'has_odt_file', 'has_html_file', 'has_description',) + search_fields = ('title',) + ordering = ('title',) + + prepopulated_fields = {'slug': ('title',)} + +admin.site.register(Book, BookAdmin) + diff --git a/catalogue/fields.py b/catalogue/fields.py new file mode 100644 index 000000000..e1a356ef0 --- /dev/null +++ b/catalogue/fields.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +from django import forms +from django.forms.widgets import flatatt +from django.forms.util import smart_unicode +from django.utils.html import escape +from django.utils.safestring import mark_safe +from django.utils.simplejson import dumps + + +class JQueryAutoCompleteWidget(forms.TextInput): + def __init__(self, source, options=None, *args, **kwargs): + self.source = source + self.options = None + if options: + self.options = dumps(options) + super(JQueryAutoCompleteWidget, self).__init__(*args, **kwargs) + + def render_js(self, field_id): + source = "'%s'" % escape(self.source) + options = '' + if self.options: + options += ', %s' % self.options + + return u'$(\'#%s\').autocomplete(%s%s);' % (field_id, source, options) + + def render(self, name, value=None, attrs=None): + final_attrs = self.build_attrs(attrs, name=name) + if value: + final_attrs['value'] = smart_unicode(value) + + if not self.attrs.has_key('id'): + final_attrs['id'] = 'id_%s' % name + + html = u''' + + ''' % { + 'attrs' : flatatt(final_attrs), + 'js' : self.render_js(final_attrs['id']), + } + + return mark_safe(html) + + +class JQueryAutoCompleteField(forms.CharField): + def __init__(self, source, options=None, *args, **kwargs): + if 'widget' not in kwargs: + kwargs['widget'] = JQueryAutoCompleteWidget(source, options) + + super(JQueryAutoCompleteField, self).__init__(*args, **kwargs) + diff --git a/catalogue/forms.py b/catalogue/forms.py new file mode 100644 index 000000000..b383f99ea --- /dev/null +++ b/catalogue/forms.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +from django import forms + +from catalogue.models import Tag +from catalogue.fields import JQueryAutoCompleteField +from catalogue.lib.slughifi import slughifi + + +class SearchForm(forms.Form): + q = JQueryAutoCompleteField('/katalog/tags/', {'minChars': 2, 'selectFirst': True, 'cacheLength': 50}) + + def __init__(self, *args, **kwargs): + super(SearchForm, self).__init__(*args, **kwargs) + self.fields['q'].widget.attrs['title'] = u'tytuł utworu, motyw lub kategoria' + + +class BookSetsForm(forms.Form): + def __init__(self, book, user, *args, **kwargs): + super(BookSetsForm, self).__init__(*args, **kwargs) + self.fields['set_ids'] = forms.MultipleChoiceField( + label=u'Zestawy', + required=False, + choices=[(tag.id, tag.name) for tag in Tag.objects.filter(category='set', user=user)], + initial=[tag.id for tag in book.tags.filter(category='set', user=user)], + widget=forms.CheckboxSelectMultiple + ) + + +class NewSetForm(forms.Form): + name = forms.CharField(max_length=50, required=True) + + def save(self, user, commit=True): + name = self.cleaned_data['name'] + new_set = Tag(name=name, slug=slughifi(name), sort_key=slughifi(name), + category='set', user=user) + + new_set.save() + return new_set + diff --git a/catalogue/lib/.DS_Store b/catalogue/lib/.DS_Store new file mode 100644 index 000000000..f4064f480 Binary files /dev/null and b/catalogue/lib/.DS_Store differ diff --git a/catalogue/lib/__init__.py b/catalogue/lib/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/catalogue/lib/dcparser/__init__.py b/catalogue/lib/dcparser/__init__.py new file mode 100644 index 000000000..793f5270d --- /dev/null +++ b/catalogue/lib/dcparser/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +from dcparser import parse, ParseError +from person import Person + diff --git a/catalogue/lib/dcparser/converters.py b/catalogue/lib/dcparser/converters.py new file mode 100644 index 000000000..773aeddcb --- /dev/null +++ b/catalogue/lib/dcparser/converters.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +from datetime import date +import time +import re + +from person import Person + + +def str_to_unicode(value): + return unicode(value) + + +def str_to_person(value): + comma_count = value.count(',') + + if comma_count == 0: + last_name, first_names = value, [] + elif comma_count == 1: + last_name, first_names = value.split(',') + first_names = [name for name in first_names.split(' ') if len(name)] + else: + raise ValueError("value contains more than one comma: %r" % value) + + return Person(last_name.strip(), *first_names) + + +def str_to_date(value): + try: + t = time.strptime(value, '%Y-%m-%d') + except ValueError: + t = time.strptime(value, '%Y') + return date(t[0], t[1], t[2]) + + diff --git a/catalogue/lib/dcparser/dcparser.py b/catalogue/lib/dcparser/dcparser.py new file mode 100644 index 000000000..e8a733a73 --- /dev/null +++ b/catalogue/lib/dcparser/dcparser.py @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- +from xml.parsers.expat import ExpatError + +# Import ElementTree from anywhere +try: + import xml.etree.ElementTree as ET # Python >= 2.5 +except ImportError: + try: + import elementtree.ElementTree as ET # effbot's pure Python module + except ImportError: + import lxml.etree as ET # ElementTree API using libxml2 + +import converters + + + +__all__ = ('parse', 'ParseError') + + + +class ParseError(Exception): + def __init__(self, message): + super(self, Exception).__init__(message) + + + +class XMLNamespace(object): + '''Represents XML namespace.''' + + def __init__(self, uri): + self.uri = uri + + def __call__(self, tag): + return '{%s}%s' % (self.uri, tag) + + def __contains__(self, tag): + return tag.startswith(str(self)) + + def __repr__(self): + return 'NS(%r)' % self.uri + + def __str__(self): + return '%s' % self.uri + + + +class BookInfo(object): + RDF = XMLNamespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#') + DC = XMLNamespace('http://purl.org/dc/elements/1.1/') + + mapping = { + DC('creator') : ('author', converters.str_to_person), + DC('title') : ('title', converters.str_to_unicode), + DC('subject.period') : ('epoch', converters.str_to_unicode), + DC('subject.type') : ('kind', converters.str_to_unicode), + DC('subject.genre') : ('genre', converters.str_to_unicode), + DC('date') : ('created_at', converters.str_to_date), + DC('date.pd') : ('released_to_public_domain_at', converters.str_to_date), + DC('contributor.translator') : ('translator', converters.str_to_person), + DC('contributor.technical_editor') : ('technical_editor', converters.str_to_person), + DC('publisher') : ('publisher', converters.str_to_unicode), + DC('source') : ('source_name', converters.str_to_unicode), + DC('source.URL') : ('source_url', converters.str_to_unicode), + } + + + @classmethod + def from_string(cls, xml): + """docstring for from_string""" + from StringIO import StringIO + return cls.from_file(StringIO(xml)) + + + @classmethod + def from_file(cls, xml_file): + book_info = cls() + + try: + tree = ET.parse(xml_file) + except ExpatError, e: + raise ParseError(e) + + description = tree.find('//' + book_info.RDF('Description')) + if description is None: + raise ParseError('no Description tag found in document') + + for element in description.findall('*'): + book_info.parse_element(element) + + return book_info + + + def parse_element(self, element): + try: + attribute, converter = self.mapping[element.tag] + setattr(self, attribute, converter(element.text)) + except KeyError: + pass + + + def to_xml(self): + """XML representation of this object.""" + ET._namespace_map[str(self.RDF)] = 'rdf' + ET._namespace_map[str(self.DC)] = 'dc' + + root = ET.Element(self.RDF('RDF')) + description = ET.SubElement(root, self.RDF('Description')) + + for tag, (attribute, converter) in self.mapping.iteritems(): + if hasattr(self, attribute): + e = ET.Element(tag) + e.text = unicode(getattr(self, attribute)) + description.append(e) + + return unicode(ET.tostring(root, 'utf-8'), 'utf-8') + + +def parse(file_name): + return BookInfo.from_file(file_name) + + diff --git a/catalogue/lib/dcparser/person.py b/catalogue/lib/dcparser/person.py new file mode 100644 index 000000000..16412f768 --- /dev/null +++ b/catalogue/lib/dcparser/person.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + + +class Person(object): + """Single person with last name and a list of first names.""" + def __init__(self, last_name, *first_names): + self.last_name = last_name + self.first_names = first_names + + + def __eq__(self, right): + return self.last_name == right.last_name and self.first_names == right.first_names + + + def __unicode__(self): + if len(self.first_names) > 0: + return '%s, %s' % (self.last_name, ' '.join(self.first_names)) + else: + return self.last_name + + + def __repr__(self): + return 'Person(last_name=%r, first_names=*%r)' % (self.last_name, self.first_names) + diff --git a/catalogue/lib/slughifi.py b/catalogue/lib/slughifi.py new file mode 100644 index 000000000..e7fa2212d --- /dev/null +++ b/catalogue/lib/slughifi.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +import re +from types import UnicodeType + +from django.template.defaultfilters import slugify + +# default unicode character mapping ( you may not see some chars, leave as is ) +char_map = {u'À': 'A', u'Á': 'A', u'Â': 'A', u'Ã': 'A', u'Ä': 'Ae', u'Å': 'A', u'Æ': 'A', u'Ā': 'A', u'Ą': 'A', u'Ă': 'A', u'Ç': 'C', u'Ć': 'C', u'Č': 'C', u'Ĉ': 'C', u'Ċ': 'C', u'Ď': 'D', u'Đ': 'D', u'È': 'E', u'É': 'E', u'Ê': 'E', u'Ë': 'E', u'Ē': 'E', u'Ę': 'E', u'Ě': 'E', u'Ĕ': 'E', u'Ė': 'E', u'Ĝ': 'G', u'Ğ': 'G', u'Ä ': 'G', u'Ä¢': 'G', u'Ĥ': 'H', u'Ħ': 'H', u'Ì': 'I', u'Í': 'I', u'Î': 'I', u'Ï': 'I', u'Ī': 'I', u'Ĩ': 'I', u'Ĭ': 'I', u'Ä®': 'I', u'Ä°': 'I', u'IJ': 'IJ', u'Ä´': 'J', u'Ķ': 'K', u'Ľ': 'K', u'Ĺ': 'K', u'Ä»': 'K', u'Ä¿': 'K', u'Ł': 'L', u'Ñ': 'N', u'Ń': 'N', u'Ň': 'N', u'Ņ': 'N', u'Ŋ': 'N', u'Ò': 'O', u'Ó': 'O', u'Ô': 'O', u'Õ': 'O', u'Ö': 'Oe', u'Ø': 'O', u'Ō': 'O', u'Ő': 'O', u'Ŏ': 'O', u'Œ': 'OE', u'Ŕ': 'R', u'Ř': 'R', u'Ŗ': 'R', u'Ś': 'S', u'Ş': 'S', u'Ŝ': 'S', u'Ș': 'S', u'Å ': 'S', u'Ť': 'T', u'Å¢': 'T', u'Ŧ': 'T', u'Ț': 'T', u'Ù': 'U', u'Ú': 'U', u'Û': 'U', u'Ü': 'Ue', u'Ū': 'U', u'Å®': 'U', u'Å°': 'U', u'Ŭ': 'U', u'Ũ': 'U', u'Ų': 'U', u'Å´': 'W', u'Ŷ': 'Y', u'Ÿ': 'Y', u'Ý': 'Y', u'Ź': 'Z', u'Å»': 'Z', u'Ž': 'Z', u'à': 'a', u'á': 'a', u'â': 'a', u'ã': 'a', u'ä': 'ae', u'ā': 'a', u'ą': 'a', u'ă': 'a', u'Ã¥': 'a', u'æ': 'ae', u'ç': 'c', u'ć': 'c', u'č': 'c', u'ĉ': 'c', u'ċ': 'c', u'ď': 'd', u'đ': 'd', u'è': 'e', u'é': 'e', u'ê': 'e', u'ë': 'e', u'ē': 'e', u'ę': 'e', u'ě': 'e', u'ĕ': 'e', u'ė': 'e', u'ƒ': 'f', u'ĝ': 'g', u'ğ': 'g', u'Ä¡': 'g', u'Ä£': 'g', u'Ä¥': 'h', u'ħ': 'h', u'ì': 'i', u'í': 'i', u'î': 'i', u'ï': 'i', u'Ä«': 'i', u'Ä©': 'i', u'Ä­': 'i', u'į': 'i', u'ı': 'i', u'ij': 'ij', u'ĵ': 'j', u'Ä·': 'k', u'ĸ': 'k', u'ł': 'l', u'ľ': 'l', u'ĺ': 'l', u'ļ': 'l', u'ŀ': 'l', u'ñ': 'n', u'ń': 'n', u'ň': 'n', u'ņ': 'n', u'ʼn': 'n', u'ŋ': 'n', u'ò': 'o', u'ó': 'o', u'ô': 'o', u'õ': 'o', u'ö': 'oe', u'ø': 'o', u'ō': 'o', u'ő': 'o', u'ŏ': 'o', u'œ': 'oe', u'ŕ': 'r', u'ř': 'r', u'ŗ': 'r', u'ś': 's', u'Å¡': 's', u'Å¥': 't', u'ù': 'u', u'ú': 'u', u'û': 'u', u'ü': 'ue', u'Å«': 'u', u'ů': 'u', u'ű': 'u', u'Å­': 'u', u'Å©': 'u', u'ų': 'u', u'ŵ': 'w', u'ÿ': 'y', u'ý': 'y', u'Å·': 'y', u'ż': 'z', u'ź': 'z', u'ž': 'z', u'ß': 'ss', u'Å¿': 'ss', u'Α': 'A', u'Ά': 'A', u'Ἀ': 'A', u'Ἁ': 'A', u'Ἂ': 'A', u'Ἃ': 'A', u'Ἄ': 'A', u'Ἅ': 'A', u'Ἆ': 'A', u'Ἇ': 'A', u'ᾈ': 'A', u'ᾉ': 'A', u'ᾊ': 'A', u'ᾋ': 'A', u'ᾌ': 'A', u'ᾍ': 'A', u'ᾎ': 'A', u'ᾏ': 'A', u'Ᾰ': 'A', u'á¾¹': 'A', u'Ὰ': 'A', u'á¾»': 'A', u'á¾¼': 'A', u'Β': 'B', u'Γ': 'G', u'Δ': 'D', u'Ε': 'E', u'Έ': 'E', u'Ἐ': 'E', u'Ἑ': 'E', u'Ἒ': 'E', u'Ἓ': 'E', u'Ἔ': 'E', u'Ἕ': 'E', u'Έ': 'E', u'Ὲ': 'E', u'Ζ': 'Z', u'Η': 'I', u'Ή': 'I', u'Ἠ': 'I', u'Ἡ': 'I', u'Ἢ': 'I', u'Ἣ': 'I', u'Ἤ': 'I', u'á¼­': 'I', u'á¼®': 'I', u'Ἧ': 'I', u'ᾘ': 'I', u'ᾙ': 'I', u'ᾚ': 'I', u'ᾛ': 'I', u'ᾜ': 'I', u'ᾝ': 'I', u'ᾞ': 'I', u'ᾟ': 'I', u'Ὴ': 'I', u'Ή': 'I', u'ῌ': 'I', u'Θ': 'TH', u'Ι': 'I', u'Ί': 'I', u'Ϊ': 'I', u'Ἰ': 'I', u'á¼¹': 'I', u'Ἲ': 'I', u'á¼»': 'I', u'á¼¼': 'I', u'á¼½': 'I', u'á¼¾': 'I', u'Ἷ': 'I', u'Ῐ': 'I', u'Ῑ': 'I', u'Ὶ': 'I', u'Ί': 'I', u'Κ': 'K', u'Λ': 'L', u'Μ': 'M', u'Ν': 'N', u'Ξ': 'KS', u'Ο': 'O', u'Ό': 'O', u'Ὀ': 'O', u'Ὁ': 'O', u'Ὂ': 'O', u'Ὃ': 'O', u'Ὄ': 'O', u'Ὅ': 'O', u'Ὸ': 'O', u'Ό': 'O', u'Π': 'P', u'Ρ': 'R', u'Ῥ': 'R', u'Σ': 'S', u'Τ': 'T', u'Î¥': 'Y', u'Ύ': 'Y', u'Ϋ': 'Y', u'Ὑ': 'Y', u'Ὓ': 'Y', u'Ὕ': 'Y', u'Ὗ': 'Y', u'Ῠ': 'Y', u'á¿©': 'Y', u'Ὺ': 'Y', u'á¿«': 'Y', u'Φ': 'F', u'Χ': 'X', u'Ψ': 'PS', u'Ω': 'O', u'Ώ': 'O', u'Ὠ': 'O', u'Ὡ': 'O', u'Ὢ': 'O', u'Ὣ': 'O', u'Ὤ': 'O', u'á½­': 'O', u'á½®': 'O', u'Ὧ': 'O', u'ᾨ': 'O', u'ᾩ': 'O', u'ᾪ': 'O', u'ᾫ': 'O', u'ᾬ': 'O', u'á¾­': 'O', u'á¾®': 'O', u'ᾯ': 'O', u'Ὼ': 'O', u'á¿»': 'O', u'ῼ': 'O', u'α': 'a', u'ά': 'a', u'ἀ': 'a', u'ἁ': 'a', u'ἂ': 'a', u'ἃ': 'a', u'ἄ': 'a', u'ἅ': 'a', u'ἆ': 'a', u'ἇ': 'a', u'ᾀ': 'a', u'ᾁ': 'a', u'ᾂ': 'a', u'ᾃ': 'a', u'ᾄ': 'a', u'ᾅ': 'a', u'ᾆ': 'a', u'ᾇ': 'a', u'á½°': 'a', u'á½±': 'a', u'á¾°': 'a', u'á¾±': 'a', u'á¾²': 'a', u'á¾³': 'a', u'á¾´': 'a', u'ᾶ': 'a', u'á¾·': 'a', u'β': 'b', u'γ': 'g', u'δ': 'd', u'ε': 'e', u'έ': 'e', u'ἐ': 'e', u'ἑ': 'e', u'ἒ': 'e', u'ἓ': 'e', u'ἔ': 'e', u'ἕ': 'e', u'á½²': 'e', u'á½³': 'e', u'ζ': 'z', u'η': 'i', u'ή': 'i', u'á¼ ': 'i', u'ἡ': 'i', u'á¼¢': 'i', u'á¼£': 'i', u'ἤ': 'i', u'á¼¥': 'i', u'ἦ': 'i', u'ἧ': 'i', u'ᾐ': 'i', u'ᾑ': 'i', u'ᾒ': 'i', u'ᾓ': 'i', u'ᾔ': 'i', u'ᾕ': 'i', u'ᾖ': 'i', u'ᾗ': 'i', u'á½´': 'i', u'á½µ': 'i', u'ῂ': 'i', u'ῃ': 'i', u'ῄ': 'i', u'ῆ': 'i', u'ῇ': 'i', u'θ': 'th', u'ι': 'i', u'ί': 'i', u'ϊ': 'i', u'ΐ': 'i', u'á¼°': 'i', u'á¼±': 'i', u'á¼²': 'i', u'á¼³': 'i', u'á¼´': 'i', u'á¼µ': 'i', u'ἶ': 'i', u'á¼·': 'i', u'ὶ': 'i', u'á½·': 'i', u'ῐ': 'i', u'ῑ': 'i', u'ῒ': 'i', u'ΐ': 'i', u'ῖ': 'i', u'ῗ': 'i', u'κ': 'k', u'λ': 'l', u'μ': 'm', u'ν': 'n', u'ξ': 'ks', u'ο': 'o', u'ό': 'o', u'ὀ': 'o', u'ὁ': 'o', u'ὂ': 'o', u'ὃ': 'o', u'ὄ': 'o', u'ὅ': 'o', u'ὸ': 'o', u'á½¹': 'o', u'π': 'p', u'ρ': 'r', u'ῤ': 'r', u'á¿¥': 'r', u'σ': 's', u'ς': 's', u'τ': 't', u'υ': 'y', u'ύ': 'y', u'ϋ': 'y', u'ΰ': 'y', u'ὐ': 'y', u'ὑ': 'y', u'ὒ': 'y', u'ὓ': 'y', u'ὔ': 'y', u'ὕ': 'y', u'ὖ': 'y', u'ὗ': 'y', u'ὺ': 'y', u'á½»': 'y', u'á¿ ': 'y', u'á¿¡': 'y', u'á¿¢': 'y', u'á¿£': 'y', u'ῦ': 'y', u'ῧ': 'y', u'φ': 'f', u'χ': 'x', u'ψ': 'ps', u'ω': 'o', u'ώ': 'o', u'á½ ': 'o', u'ὡ': 'o', u'á½¢': 'o', u'á½£': 'o', u'ὤ': 'o', u'á½¥': 'o', u'ὦ': 'o', u'ὧ': 'o', u'á¾ ': 'o', u'ᾡ': 'o', u'á¾¢': 'o', u'á¾£': 'o', u'ᾤ': 'o', u'á¾¥': 'o', u'ᾦ': 'o', u'ᾧ': 'o', u'á½¼': 'o', u'á½½': 'o', u'ῲ': 'o', u'ῳ': 'o', u'á¿´': 'o', u'ῶ': 'o', u'á¿·': 'o', u'¨': '', u'΅': '', u'᾿': '', u'῾': '', u'῍': '', u'῝': '', u'῎': '', u'῞': '', u'῏': '', u'῟': '', u'῀': '', u'῁': '', u'΄': '', u'á¿®': '', u'`': '', u'á¿­': '', u'ͺ': '', u'á¾½': '', u'А': 'A', u'Б': 'B', u'В': 'V', u'Г': 'G', u'Д': 'D', u'Е': 'E', u'Ё': 'E', u'Ж': 'ZH', u'З': 'Z', u'И': 'I', u'Й': 'I', u'К': 'K', u'Л': 'L', u'М': 'M', u'Н': 'N', u'О': 'O', u'П': 'P', u'Р': 'R', u'С': 'S', u'Т': 'T', u'У': 'U', u'Ф': 'F', u'Ð¥': 'KH', u'Ц': 'TS', u'Ч': 'CH', u'Ш': 'SH', u'Щ': 'SHCH', u'Ы': 'Y', u'Э': 'E', u'Ю': 'YU', u'Я': 'YA', u'а': 'A', u'б': 'B', u'в': 'V', u'г': 'G', u'д': 'D', u'е': 'E', u'ё': 'E', u'ж': 'ZH', u'з': 'Z', u'и': 'I', u'й': 'I', u'к': 'K', u'л': 'L', u'м': 'M', u'н': 'N', u'о': 'O', u'п': 'P', u'р': 'R', u'с': 'S', u'т': 'T', u'у': 'U', u'ф': 'F', u'х': 'KH', u'ц': 'TS', u'ч': 'CH', u'ш': 'SH', u'щ': 'SHCH', u'ы': 'Y', u'э': 'E', u'ю': 'YU', u'я': 'YA', u'Ъ': '', u'ъ': '', u'Ь': '', u'ь': '', u'ð': 'd', u'Ð': 'D', u'þ': 'th', u'Þ': 'TH', + u'ა': 'a', u'ბ': 'b', u'გ': 'g', u'დ': 'd', u'ე': 'e', u'ვ': 'v', u'ზ': 'z', u'თ': 't', u'ი': 'i', u'კ': 'k', u'ლ': 'l', u'მ': 'm', u'ნ': 'n', u'ო': 'o', u'პ': 'p', u'ჟ': 'zh', u'რ': 'r', u'ს': 's', u'ტ': 't', u'უ': 'u', u'ფ': 'p', u'ქ': 'k', u'ღ': 'gh', u'ყ': 'q', u'შ': 'sh', u'ჩ': 'ch', u'ც': 'ts', u'ძ': 'dz', u'წ': 'ts', u'ჭ': 'ch', u'ხ': 'kh', u'ჯ': 'j', u'ჰ': 'h' } + +def replace_char(m): + char = m.group() + if char_map.has_key(char): + return char_map[char] + else: + return char + +def slughifi(value, do_slugify=True, overwrite_char_map={}): + """ + High Fidelity slugify - slughifi.py, v 0.1 + + Examples : + + >>> text = 'C\'est déjà l\'été.' + + >>> slughifi(text) + 'cest-deja-lete' + + >>> slughifi(text, overwrite_char_map={u'\'': '-',}) + 'c-est-deja-l-ete' + + >>> slughifi(text, do_slugify=False) + "C'est deja l'ete." + + # Normal slugify removes accented characters + >>> slugify(text) + 'cest-dj-lt' + + """ + + # unicodification + if type(value) != UnicodeType: + value = unicode(value, 'utf-8', 'ignore') + + # overwrite chararcter mapping + char_map.update(overwrite_char_map) + + # try to replace chars + value = re.sub('[^a-zA-Z0-9\\s\\-]{1}', replace_char, value) + + # apply django default slugify + if do_slugify: + value = slugify(value) + + return value.encode('ascii', 'ignore') + diff --git a/catalogue/management/.DS_Store b/catalogue/management/.DS_Store new file mode 100644 index 000000000..d58b7f84a Binary files /dev/null and b/catalogue/management/.DS_Store differ diff --git a/catalogue/management/__init__.py b/catalogue/management/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/catalogue/management/commands/.DS_Store b/catalogue/management/commands/.DS_Store new file mode 100644 index 000000000..5008ddfcf Binary files /dev/null and b/catalogue/management/commands/.DS_Store differ diff --git a/catalogue/management/commands/__init__.py b/catalogue/management/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/catalogue/management/commands/importbooks.py b/catalogue/management/commands/importbooks.py new file mode 100644 index 000000000..24908fe44 --- /dev/null +++ b/catalogue/management/commands/importbooks.py @@ -0,0 +1,66 @@ +from django.core.management.base import BaseCommand, CommandError +from django.core.management.color import color_style +from optparse import make_option +import sys +import os + +from catalogue.lib.dcparser import parse +from catalogue.lib.slughifi import slughifi +from catalogue.models import Book, Tag + + +class Command(BaseCommand): + option_list = BaseCommand.option_list + ( + make_option('--verbosity', action='store', dest='verbosity', default='1', + type='choice', choices=['0', '1', '2'], + help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), + ) + help = 'Imports books from the specified directories.' + args = 'directory [directory ...]' + + def handle(self, *directories, **options): + from django.db import transaction + + self.style = color_style() + + verbosity = int(options.get('verbosity', 1)) + show_traceback = options.get('traceback', False) + + # Start transaction management. + transaction.commit_unless_managed() + transaction.enter_transaction_management() + transaction.managed(True) + + for dir_name in directories: + if not os.path.isdir(dir_name): + print self.style.ERROR("Skipping '%s': not a directory." % dir_name) + else: + for file_name in os.listdir(dir_name): + file_path = os.path.join(dir_name, file_name) + if not os.path.splitext(file_name)[1] == '.xml': + print self.style.NOTICE("Skipping '%s': not an XML file." % file_path) + continue + if verbosity > 1: + print "Parsing '%s'" % file_path + + book_info = parse(file_path) + book = Book(title=book_info.title, slug=slughifi(book_info.title)) + book.save() + + book_tags = [] + for category in ('kind', 'genre', 'author', 'epoch'): + tag_name = getattr(book_info, category) + tag_sort_key = tag_name + if category == 'author': + tag_sort_key = tag_name.last_name + tag_name = ' '.join(tag_name.first_names) + ' ' + tag_name.last_name + tag, created = Tag.objects.get_or_create(name=tag_name, + slug=slughifi(tag_name), sort_key=slughifi(tag_sort_key), category=category) + tag.save() + book_tags.append(tag) + book.tags = book_tags + + + transaction.commit() + transaction.leave_transaction_management() + diff --git a/catalogue/models.py b/catalogue/models.py new file mode 100644 index 000000000..b49747b18 --- /dev/null +++ b/catalogue/models.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +from django.db import models +from django.db.models import permalink +from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth.models import User + +from newtagging.models import TagBase +from newtagging import managers + + +TAG_CATEGORIES = ( + ('author', _('author')), + ('epoch', _('epoch')), + ('kind', _('kind')), + ('genre', _('genre')), + ('theme', _('theme')), + ('set', _('set')), +) + + +class TagSubcategoryManager(models.Manager): + def __init__(self, subcategory): + super(TagSubcategoryManager, self).__init__() + self.subcategory = subcategory + + def get_query_set(self): + return super(TagSubcategoryManager, self).get_query_set().filter(category=self.subcategory) + + +class Tag(TagBase): + name = models.CharField(_('name'), max_length=50, unique=True, db_index=True) + slug = models.SlugField(_('slug'), unique=True, db_index=True) + sort_key = models.SlugField(_('sort key'), db_index=True) + category = models.CharField(_('category'), max_length=50, blank=False, null=False, + db_index=True, choices=TAG_CATEGORIES) + description = models.TextField(blank=True) + + user = models.ForeignKey(User, blank=True, null=True) + + def has_description(self): + return len(self.description) > 0 + has_description.short_description = _('Has description') + has_description.boolean = True + + @permalink + def get_absolute_url(self): + return ('catalogue.views.tagged_book_list', [self.slug]) + + class Meta: + ordering = ('sort_key',) + verbose_name = _('tag') + verbose_name_plural = _('tags') + + def __unicode__(self): + return self.name + + +class Book(models.Model): + title = models.CharField(_('title'), max_length=120) + slug = models.SlugField(_('slug'), unique=True, db_index=True) + description = models.TextField(_('description'), blank=True) + created_at = models.DateTimeField(_('creation date'), auto_now=True) + + # Formats + pdf_file = models.FileField(_('PDF file'), upload_to='books/pdf', blank=True) + odt_file = models.FileField(_('ODT file'), upload_to='books/odt', blank=True) + html_file = models.FileField(_('HTML file'), upload_to='books/html', blank=True) + + objects = managers.ModelTaggedItemManager(Tag) + tags = managers.TagDescriptor(Tag) + + def has_description(self): + return len(self.description) > 0 + has_description.short_description = _('Has description') + has_description.boolean = True + + def has_pdf_file(self): + return bool(self.pdf_file) + has_pdf_file.short_description = 'PDF' + has_pdf_file.boolean = True + + def has_odt_file(self): + return bool(self.odt_file) + has_odt_file.short_description = 'ODT' + has_odt_file.boolean = True + + def has_html_file(self): + return bool(self.html_file) + has_html_file.short_description = 'HTML' + has_html_file.boolean = True + + @permalink + def get_absolute_url(self): + return ('catalogue.views.book_detail', [self.slug]) + + class Meta: + ordering = ('title',) + verbose_name = _('book') + verbose_name_plural = _('books') + + def __unicode__(self): + return self.title + + +# class Fragment(models.Model): +# id = models.IntegerField(primary_key=True) +# text = models.TextField(blank=True) +# start_paragraph = models.IntegerField(null=True, blank=True) +# book_id = models.IntegerField(null=True, blank=True) +# class Meta: +# db_table = u'fragment' + + +# class Inflections(models.Model): +# word = models.CharField(max_length=120, primary_key=True) +# cases = models.TextField() # This field type is a guess. +# class Meta: +# db_table = u'inflections' + + +# class Paragraph(models.Model): +# id = models.IntegerField(primary_key=True) +# number = models.IntegerField(null=True, blank=True) +# text = models.TextField(blank=True) +# book_id = models.IntegerField(null=True, blank=True) +# class Meta: +# db_table = u'paragraph' + diff --git a/catalogue/templatetags/__init__.py b/catalogue/templatetags/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/catalogue/templatetags/catalogue.py b/catalogue/templatetags/catalogue.py new file mode 100644 index 000000000..1bf250c18 --- /dev/null +++ b/catalogue/templatetags/catalogue.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- +from django import template +from django.template import Node, Variable +from django.utils.encoding import smart_str +from django.core.urlresolvers import reverse + + +register = template.Library() + + +def iterable(obj): + try: + iter(obj) + return True + except TypeError: + return False + + +def capfirst(text): + try: + return '%s%s' % (text[0].upper(), text[1:]) + except IndexError: + return '' + + +@register.simple_tag +def title_from_tags(tags): + def split_tags(tags): + result = {} + for tag in tags: + result[tag.category] = tag + return result + + class Flection(object): + def get_case(self, name, flection): + return name + flection = Flection() + + self = split_tags(tags) + + title = u'' + + # Specjalny przypadek "Twórczość w pozytywizmie", wtedy gdy tylko epoka + # jest wybrana przez użytkownika + if 'epoch' in self and len(self) == 1: + text = u'Twórczość w %s' % flection.get_case(unicode(self['epoch']), u'miejscownik') + return capfirst(text) + + # Specjalny przypadek "Dramat w twórczości Sofoklesa", wtedy gdy podane + # są tylko rodzaj literacki i autor + if 'kind' in self and 'author' in self and len(self) == 2: + text = u'%s w twórczości %s' % (unicode(self['kind']), + flection.get_case(unicode(self['author']), u'dopełniacz')) + return capfirst(text) + + # Przypadki ogólniejsze + if 'theme' in self: + title += u'Motyw %s' % unicode(self['theme']) + + if 'genre' in self: + if 'theme' in self: + title += u' w %s' % flection.get_case(unicode(self['genre']), u'miejscownik') + else: + title += unicode(self['genre']) + + if 'kind' in self or 'author' in self or 'epoch' in self: + if 'genre' in self or 'theme' in self: + if 'kind' in self: + title += u' w %s ' % flection.get_case(unicode(self['kind']), u'miejscownik') + else: + title += u' w twórczości ' + else: + title += u'%s ' % unicode(self.get('kind', u'twórczość')) + + if 'author' in self: + title += flection.get_case(unicode(self['author']), u'dopełniacz') + elif 'epoch' in self: + title += flection.get_case(unicode(self['epoch']), u'dopełniacz') + + return capfirst(title) + + +@register.tag +def catalogue_url(parser, token): + bits = token.split_contents() + tag_name = bits[0] + + tags_to_add = [] + tags_to_remove = [] + for bit in bits[1:]: + if bit[0] == '-': + tags_to_remove.append(bit[1:]) + else: + tags_to_add.append(bit) + + return CatalogueURLNode(tags_to_add, tags_to_remove) + + +class CatalogueURLNode(Node): + def __init__(self, tags_to_add, tags_to_remove): + self.tags_to_add = [Variable(tag) for tag in tags_to_add] + self.tags_to_remove = [Variable(tag) for tag in tags_to_remove] + + def render(self, context): + tags_to_add = [] + tags_to_remove = [] + + for tag_variable in self.tags_to_add: + tag = tag_variable.resolve(context) + if isinstance(tag, (list, dict)): + tags_to_add += [t for t in tag] + else: + tags_to_add.append(tag) + + for tag_variable in self.tags_to_remove: + tag = tag_variable.resolve(context) + if iterable(tag): + tags_to_remove += [t for t in tag] + else: + tags_to_remove.append(tag) + + tag_slugs = [tag.slug for tag in tags_to_add] + for tag in tags_to_remove: + try: + tag_slugs.remove(tag.slug) + except KeyError: + pass + + if len(tag_slugs) > 0: + return reverse('tagged_book_list', kwargs={'tags': '/'.join(tag_slugs)}) + else: + return reverse('main_page') + + +@register.inclusion_tag('catalogue/latest_blog_posts.html') +def latest_blog_posts(feed_url, posts_to_show=5): + import feedparser + import datetime + + feed = feedparser.parse(feed_url) + posts = [] + for i in range(posts_to_show): + pub_date = feed['entries'][i].updated_parsed + published = datetime.date(pub_date[0], pub_date[1], pub_date[2] ) + posts.append({ + 'title': feed['entries'][i].title, + 'summary': feed['entries'][i].summary, + 'link': feed['entries'][i].link, + 'date': published, + }) + return {'posts': posts} + diff --git a/catalogue/urls.py b/catalogue/urls.py new file mode 100644 index 000000000..fb20dd1f5 --- /dev/null +++ b/catalogue/urls.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +import os + +from django.conf.urls.defaults import * +from django.views.generic.simple import redirect_to + + +urlpatterns = patterns('catalogue.views', + url(r'^$', 'main_page', name='main_page'), + url(r'^lektury/', 'book_list'), + url(r'^lektura/(?P[a-zA-Z0-9-]+)/zestawy/', 'book_sets'), + url(r'^zestawy/nowy/$', 'new_set'), + url(r'^lektura/(?P[a-zA-Z0-9-]+)/$', 'book_detail'), + url(r'^tags/$', 'tags_starting_with', name='hint'), + url(r'^(?P[a-zA-Z-/]+)/$', 'tagged_book_list', name='tagged_book_list'), +) + diff --git a/catalogue/utils.py b/catalogue/utils.py new file mode 100644 index 000000000..d1cee5045 --- /dev/null +++ b/catalogue/utils.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- + + +def split_tags(tags): + result = {} + for tag in tags: + result.setdefault(tag.category, []).append(tag) + return result + diff --git a/catalogue/views.py b/catalogue/views.py new file mode 100644 index 000000000..a0315a4c6 --- /dev/null +++ b/catalogue/views.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +from django.template import RequestContext +from django.shortcuts import render_to_response, get_object_or_404 +from django.http import HttpResponse, HttpResponseRedirect, Http404 +from django.core.urlresolvers import reverse +from django.db.models import Q +from django.contrib.auth.decorators import login_required +from django.utils.datastructures import SortedDict +from django.views.decorators.http import require_POST + +from catalogue import models +from catalogue import forms +from catalogue.utils import split_tags + + +def catalogue_redirect(request, tags=''): + if len(request.GET['q']) > 0: + try: + tag = models.Tag.objects.get(name=request.GET['q']) + if len(tags): + tags += '/' + tags = tags + tag.slug + except models.Tag.DoesNotExist: + book = get_object_or_404(models.Book, title=request.GET['q']) + return HttpResponseRedirect(book.get_absolute_url()) + if len(tags) > 0: + return HttpResponseRedirect(reverse('catalogue.views.tagged_book_list', kwargs=dict(tags=tags))) + else: + return HttpResponseRedirect(reverse('catalogue.views.main_page')) + + +def tags_starting_with(request): + try: + prefix = request.GET['q'] + if len(prefix) < 2: + raise KeyError + + books = models.Book.objects.filter(title__icontains=prefix) + tags = models.Tag.objects.filter(name__icontains=prefix) + if request.user.is_authenticated(): + tags = tags.filter(~Q(category='set') | Q(user=request.user)) + else: + tags = tags.filter(~Q(category='set')) + + completions = [book.title for book in books] + [tag.name for tag in tags] + + return HttpResponse('\n'.join(completions)) + + except KeyError: + return HttpResponse('') + + +def main_page(request): + if 'q' in request.GET: + return catalogue_redirect(request) + + if request.user.is_authenticated(): + extra_where = '(NOT catalogue_tag.category = "set" OR catalogue_tag.user_id = %d)' % request.user.id + else: + extra_where = 'NOT catalogue_tag.category = "set"' + tags = models.Tag.objects.usage_for_model(models.Book, counts=True, extra={'where': [extra_where]}) + categories = split_tags(tags) + + form = forms.SearchForm() + return render_to_response('catalogue/main_page.html', locals(), + context_instance=RequestContext(request)) + + +def book_list(request): + if 'q' in request.GET: + return catalogue_redirect(request) + + books = models.Book.objects.all() + form = forms.SearchForm() + + books_by_first_letter = SortedDict() + for book in books: + books_by_first_letter.setdefault(book.title[0], []).append(book) + + return render_to_response('catalogue/book_list.html', locals(), + context_instance=RequestContext(request)) + + +def tagged_book_list(request, tags=''): + if 'q' in request.GET: + return catalogue_redirect(request, tags) + + choices_split = tags.split('/') + tags = [] + for tag in choices_split: + tag = get_object_or_404(models.Tag, slug=tag) + if tag.category == 'set' and (not request.user.is_authenticated() or request.user != tag.user): + raise Http404 + tags.append(tag) + + books = models.Book.objects.with_all(tags) + + if request.user.is_authenticated(): + extra_where = '(NOT catalogue_tag.category = "set" OR catalogue_tag.user_id = %d)' % request.user.id + else: + extra_where = 'NOT catalogue_tag.category = "set"' + related_tags = models.Tag.objects.related_for_model(tags, models.Book, counts=True, extra={'where': [extra_where]}) + categories = split_tags(related_tags) + + form = forms.SearchForm() + + return render_to_response('catalogue/tagged_book_list.html', dict( + tags=tags, + form=form, + books=books, + categories=categories, + ), context_instance=RequestContext(request)) + + +def book_detail(request, slug): + book = get_object_or_404(models.Book, slug=slug) + tags = list(book.tags.filter(~Q(category='set'))) + categories = split_tags(tags) + search_form = forms.SearchForm() + + return render_to_response('catalogue/book_detail.html', locals(), + context_instance=RequestContext(request)) + + +@login_required +def book_sets(request, slug): + book = get_object_or_404(models.Book, slug=slug) + user_sets = models.Tag.objects.filter(category='set', user=request.user) + book_sets = book.tags.filter(category='set', user=request.user) + + if request.method == 'POST': + form = forms.BookSetsForm(book, request.user, request.POST) + if form.is_valid(): + book.tags = ([models.Tag.objects.get(pk=id) for id in form.cleaned_data['set_ids']] + + list(book.tags.filter(~Q(category='set') | ~Q(user=request.user)))) + if request.is_ajax(): + return HttpResponse('

Zestawy zostały zapisane

') + else: + return HttpResponseRedirect('/') + else: + form = forms.BookSetsForm(book, request.user) + new_set_form = forms.NewSetForm() + + return render_to_response('catalogue/book_sets.html', locals(), + context_instance=RequestContext(request)) + +@login_required +@require_POST +def new_set(request): + new_set_form = forms.NewSetForm(request.POST) + if new_set_form.is_valid(): + new_set = new_set_form.save(request.user) + return HttpResponse('

Zestaw %s został utworzony

' % new_set) + + return render_to_response('catalogue/book_sets.html', locals(), + context_instance=RequestContext(request)) + diff --git a/chunks/__init__.py b/chunks/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/chunks/admin.py b/chunks/admin.py new file mode 100644 index 000000000..29c1fc24f --- /dev/null +++ b/chunks/admin.py @@ -0,0 +1,11 @@ +from django.contrib import admin + +from chunks.models import Chunk + + +class ChunkAdmin(admin.ModelAdmin): + list_display = ('key',) + search_fields = ('key', 'content') + +admin.site.register(Chunk, ChunkAdmin) + diff --git a/chunks/models.py b/chunks/models.py new file mode 100644 index 000000000..ac164524b --- /dev/null +++ b/chunks/models.py @@ -0,0 +1,22 @@ +from django.db import models +from django.utils.translation import ugettext_lazy as _ + + +class Chunk(models.Model): + """ + A Chunk is a piece of content associated + with a unique key that can be inserted into + any template with the use of a special template + tag + """ + key = models.CharField(_('key'), help_text=_('A unique name for this chunk of content'), primary_key=True, max_length=255) + content = models.TextField(_('content'), blank=True) + + class Meta: + ordering = ('key',) + verbose_name = _('chunk') + verbose_name_plural = _('chunks') + + def __unicode__(self): + return u'%s' % (self.key,) + diff --git a/chunks/templatetags/__init__.py b/chunks/templatetags/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/chunks/templatetags/chunks.py b/chunks/templatetags/chunks.py new file mode 100644 index 000000000..fe8efdefe --- /dev/null +++ b/chunks/templatetags/chunks.py @@ -0,0 +1,45 @@ +from django import template +from django.db import models +from django.core.cache import cache + +register = template.Library() + +Chunk = models.get_model('chunks', 'chunk') +CACHE_PREFIX = "chunk_" + +def do_get_chunk(parser, token): + # split_contents() knows not to split quoted strings. + tokens = token.split_contents() + if len(tokens) < 2 or len(tokens) > 3: + raise template.TemplateSyntaxError, "%r tag should have either 2 or 3 arguments" % (tokens[0],) + if len(tokens) == 2: + tag_name, key = tokens + cache_time = 0 + if len(tokens) == 3: + tag_name, key, cache_time = tokens + # Check to see if the key is properly double/single quoted + if not (key[0] == key[-1] and key[0] in ('"', "'")): + raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name + # Send key without quotes and caching time + return ChunkNode(key[1:-1], cache_time) + +class ChunkNode(template.Node): + def __init__(self, key, cache_time=0): + self.key = key + self.cache_time = cache_time + + def render(self, context): + try: + cache_key = CACHE_PREFIX + self.key + c = cache.get(cache_key) + if c is None: + c = Chunk.objects.get(key=self.key) + cache.set(cache_key, c, int(self.cache_time)) + content = c.content + except Chunk.DoesNotExist: + n = Chunk(key=self.key) + n.save() + return 'SOME TEXT PLEASE' + return content + +register.tag('chunk', do_get_chunk) diff --git a/compress/__init__.py b/compress/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/compress/conf/__init__.py b/compress/conf/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/compress/conf/settings.py b/compress/conf/settings.py new file mode 100644 index 000000000..f6949a201 --- /dev/null +++ b/compress/conf/settings.py @@ -0,0 +1,22 @@ +from django.core.exceptions import ImproperlyConfigured +from django.conf import settings + +COMPRESS = getattr(settings, 'COMPRESS', not settings.DEBUG) +COMPRESS_AUTO = getattr(settings, 'COMPRESS_AUTO', True) +COMPRESS_VERSION = getattr(settings, 'COMPRESS_VERSION', False) +COMPRESS_VERSION_PLACEHOLDER = getattr(settings, 'COMPRESS_VERSION_PLACEHOLDER', '?') +COMPRESS_VERSION_DEFAULT = getattr(settings, 'COMPRESS_VERSION_DEFAULT', '0') + +COMPRESS_CSS_FILTERS = getattr(settings, 'COMPRESS_CSS_FILTERS', ['compress.filters.csstidy.CSSTidyFilter']) +COMPRESS_JS_FILTERS = getattr(settings, 'COMPRESS_JS_FILTERS', ['compress.filters.jsmin.JSMinFilter']) +COMPRESS_CSS = getattr(settings, 'COMPRESS_CSS', {}) +COMPRESS_JS = getattr(settings, 'COMPRESS_JS', {}) + +if COMPRESS_CSS_FILTERS is None: + COMPRESS_CSS_FILTERS = [] + +if COMPRESS_JS_FILTERS is None: + COMPRESS_JS_FILTERS = [] + +if COMPRESS_VERSION and not COMPRESS_AUTO: + raise ImproperlyConfigured('COMPRESS_AUTO needs to be True when using COMPRESS_VERSION.') diff --git a/compress/filter_base.py b/compress/filter_base.py new file mode 100644 index 000000000..9b98531b6 --- /dev/null +++ b/compress/filter_base.py @@ -0,0 +1,14 @@ +class FilterBase: + def __init__(self, verbose): + self.verbose = verbose + + def filter_css(self, css): + raise NotImplementedError + def filter_js(self, js): + raise NotImplementedError + +class FilterError(Exception): + """ + This exception is raised when a filter fails + """ + pass \ No newline at end of file diff --git a/compress/filters/__init__.py b/compress/filters/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/compress/filters/csstidy/__init__.py b/compress/filters/csstidy/__init__.py new file mode 100644 index 000000000..d40e8eebb --- /dev/null +++ b/compress/filters/csstidy/__init__.py @@ -0,0 +1,33 @@ +import os +import warnings +import tempfile + +from django.conf import settings + +from compress.filter_base import FilterBase + +BINARY = getattr(settings, 'CSSTIDY_BINARY', 'csstidy') +ARGUMENTS = getattr(settings, 'CSSTIDY_ARGUMENTS', '--template=highest') + +warnings.simplefilter('ignore', RuntimeWarning) + +class CSSTidyFilter(FilterBase): + def filter_css(self, css): + tmp_file = tempfile.NamedTemporaryFile(mode='w+b') + tmp_file.write(css) + tmp_file.flush() + + output_file = tempfile.NamedTemporaryFile(mode='w+b') + + command = '%s %s %s %s' % (BINARY, tmp_file.name, ARGUMENTS, output_file.name) + + command_output = os.popen(command).read() + + filtered_css = output_file.read() + output_file.close() + tmp_file.close() + + if self.verbose: + print command_output + + return filtered_css diff --git a/compress/filters/csstidy_python/__init__.py b/compress/filters/csstidy_python/__init__.py new file mode 100644 index 000000000..7d581ed43 --- /dev/null +++ b/compress/filters/csstidy_python/__init__.py @@ -0,0 +1,19 @@ +from django.conf import settings + +from compress.filter_base import FilterBase +from compress.filters.csstidy_python.csstidy import CSSTidy + +COMPRESS_CSSTIDY_SETTINGS = getattr(settings, 'COMPRESS_CSSTIDY_SETTINGS', {}) + +class CSSTidyFilter(FilterBase): + def filter_css(self, css): + tidy = CSSTidy() + + for k, v in COMPRESS_CSSTIDY_SETTINGS.items(): + tidy.setSetting(k, v) + + tidy.parse(css) + + r = tidy.Output('string') + + return r diff --git a/compress/filters/csstidy_python/csstidy.py b/compress/filters/csstidy_python/csstidy.py new file mode 100644 index 000000000..6ae8dc732 --- /dev/null +++ b/compress/filters/csstidy_python/csstidy.py @@ -0,0 +1,636 @@ +# CSSTidy - CSS Parse +# +# CSS Parser class +# +# This file is part of CSSTidy. +# +# CSSTidy is free software you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation either version 2 of the License, or +# (at your option) any later version. +# +# CSSTidy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with CSSTidy if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# @license http://opensource.org/licenses/gpl-license.php GNU Public License +# @package csstidy +# @author Dj Gilcrease (digitalxero at gmail dot com) 2005-2006 + +import re + +from optimizer import CSSOptimizer +from output import CSSPrinter +import data +from tools import SortedDict + +class CSSTidy(object): + #Saves the parsed CSS + _css = "" + _raw_css = SortedDict() + _optimized_css = SortedDict() + + #List of Tokens + _tokens = [] + + #Printer class + _output = None + + #Optimiser class + _optimizer = None + + #Saves the CSS charset (@charset) + _charset = '' + + #Saves all @import URLs + _import = [] + + #Saves the namespace + _namespace = '' + + #Contains the version of csstidy + _version = '1.3' + + #Stores the settings + _settings = {} + + # Saves the parser-status. + # + # Possible values: + # - is = in selector + # - ip = in property + # - iv = in value + # - instr = in string (started at " or ' or ( ) + # - ic = in comment (ignore everything) + # - at = in @-block + _status = 'is' + + #Saves the current at rule (@media) + _at = '' + + #Saves the current selector + _selector = '' + + #Saves the current property + _property = '' + + #Saves the position of , in selectors + _sel_separate = [] + + #Saves the current value + _value = '' + + #Saves the current sub-value + _sub_value = '' + + #Saves all subvalues for a property. + _sub_value_arr = [] + + #Saves the char which opened the last string + _str_char = '' + _cur_string = '' + + #Status from which the parser switched to ic or instr + _from = '' + + #Variable needed to manage string-in-strings, for example url("foo.png") + _str_in_str = False + + #=True if in invalid at-rule + _invalid_at = False + + #=True if something has been added to the current selector + _added = False + + #Saves the message log + _log = SortedDict() + + #Saves the line number + _line = 1 + + def __init__(self): + self._settings['remove_bslash'] = True + self._settings['compress_colors'] = True + self._settings['compress_font-weight'] = True + self._settings['lowercase_s'] = False + self._settings['optimise_shorthands'] = 2 + self._settings['remove_last_'] = False + self._settings['case_properties'] = 1 + self._settings['sort_properties'] = False + self._settings['sort_selectors'] = False + self._settings['merge_selectors'] = 2 + self._settings['discard_invalid_properties'] = False + self._settings['css_level'] = 'CSS2.1' + self._settings['preserve_css'] = False + self._settings['timestamp'] = False + self._settings['template'] = 'highest_compression' + + #Maps self._status to methods + self.__statusMethod = {'is':self.__parseStatus_is, 'ip': self.__parseStatus_ip, 'iv':self.__parseStatus_iv, 'instr':self.__parseStatus_instr, 'ic':self.__parseStatus_ic, 'at':self.__parseStatus_at} + + self._output = CSSPrinter(self) + self._optimizer = CSSOptimizer(self) + + #Public Methods + def getSetting(self, setting): + return self._settings.get(setting, False) + + #Set the value of a setting. + def setSetting(self, setting, value): + self._settings[setting] = value + return True + + def log(self, message, ttype, line = -1): + if line == -1: + line = self._line + + line = int(line) + + add = {'m': message, 't': ttype} + + if not self._log.has_key(line): + self._log[line] = [] + self._log[line].append(add) + elif add not in self._log[line]: + self._log[line].append(add) + + + #Checks if a character is escaped (and returns True if it is) + def escaped(self, string, pos): + return not (string[pos-1] != '\\' or self.escaped(string, pos-1)) + + #Adds CSS to an existing media/selector + def merge_css_blocks(self, media, selector, css_add): + for prop, value in css_add.iteritems(): + self.__css_add_property(media, selector, prop, value, False) + + #Checks if $value is !important. + def is_important(self, value): + return '!important' in value.lower() + + #Returns a value without !important + def gvw_important(self, value): + if self.is_important(value): + ret = value.strip() + ret = ret[0:-9] + ret = ret.strip() + ret = ret[0:-1] + ret = ret.strip() + return ret + + return value + + def parse(self, cssString): + #Switch from \r\n to \n + self._css = cssString.replace("\r\n", "\n") + ' ' + self._raw_css = {} + self._optimized_css = {} + self._curComment = '' + + #Start Parsing + i = 0 + while i < len(cssString): + if self._css[i] == "\n" or self._css[i] == "\r": + self._line += 1 + + i += self.__statusMethod[self._status](i) + + i += 1; + + self._optimized_css = self._optimizer.optimize(self._raw_css) + + def parseFile(self, filename): + try: + f = open(filename, "r") + self.parse(f.read()) + finally: + f.close() + + #Private Methods + def __parseStatus_is(self, idx): + """ + Parse in Selector + """ + ret = 0 + + if self.__is_token(self._css, idx): + if self._css[idx] == '/' and self._css[idx+1] == '*' and self._selector.strip() == '': + self._status = 'ic' + self._from = 'is' + return 1 + + elif self._css[idx] == '@' and self._selector.strip() == '': + #Check for at-rule + self._invalid_at = True + + for name, ttype in data.at_rules.iteritems(): + if self._css[idx+1:len(name)].lower() == name.lower(): + if ttype == 'at': + self._at = '@' + name + else: + self._selector = '@' + name + + self._status = ttype + self._invalid_at = False + ret += len(name) + + if self._invalid_at: + self._selector = '@' + invalid_at_name = '' + for j in xrange(idx+1, len(self._css)): + if not self._css[j].isalpha(): + break; + + invalid_at_name += self._css[j] + + self.log('Invalid @-rule: ' + invalid_at_name + ' (removed)', 'Warning') + + elif self._css[idx] == '"' or self._css[idx] == "'": + self._cur_string = self._css[idx] + self._status = 'instr' + self._str_char = self._css[idx] + self._from = 'is' + + elif self._invalid_at and self._css[idx] == ';': + self._invalid_at = False + self._status = 'is' + + elif self._css[idx] == '{': + self._status = 'ip' + self.__add_token(data.SEL_START, self._selector) + self._added = False; + + elif self._css[idx] == '}': + self.__add_token(data.AT_END, self._at) + self._at = '' + self._selector = '' + self._sel_separate = [] + + elif self._css[idx] == ',': + self._selector = self._selector.strip() + ',' + self._sel_separate.append(len(self._selector)) + + elif self._css[idx] == '\\': + self._selector += self.__unicode(idx) + + #remove unnecessary universal selector, FS#147 + elif not (self._css[idx] == '*' and self._css[idx+1] in ('.', '#', '[', ':')): + self._selector += self._css[idx] + + else: + lastpos = len(self._selector)-1 + + if lastpos == -1 or not ((self._selector[lastpos].isspace() or self.__is_token(self._selector, lastpos) and self._selector[lastpos] == ',') and self._css[idx].isspace()): + self._selector += self._css[idx] + + return ret + + def __parseStatus_ip(self, idx): + """ + Parse in property + """ + if self.__is_token(self._css, idx): + if (self._css[idx] == ':' or self._css[idx] == '=') and self._property != '': + self._status = 'iv' + + if not self.getSetting('discard_invalid_properties') or self.__property_is_valid(self._property): + self.__add_token(data.PROPERTY, self._property) + + elif self._css[idx] == '/' and self._css[idx+1] == '*' and self._property == '': + self._status = 'ic' + self._from = 'ip' + return 1 + + elif self._css[idx] == '}': + self.__explode_selectors() + self._status = 'is' + self._invalid_at = False + self.__add_token(data.SEL_END, self._selector) + self._selector = '' + self._property = '' + + elif self._css[idx] == ';': + self._property = '' + + elif self._css[idx] == '\\': + self._property += self.__unicode(idx) + + elif not self._css[idx].isspace(): + self._property += self._css[idx] + + return 0 + + def __parseStatus_iv(self, idx): + """ + Parse in value + """ + pn = (( self._css[idx] == "\n" or self._css[idx] == "\r") and self.__property_is_next(idx+1) or idx == len(self._css)) #CHECK# + if self.__is_token(self._css, idx) or pn: + if self._css[idx] == '/' and self._css[idx+1] == '*': + self._status = 'ic' + self._from = 'iv' + return 1 + + elif self._css[idx] == '"' or self._css[idx] == "'" or self._css[idx] == '(': + self._cur_string = self._css[idx] + self._str_char = ')' if self._css[idx] == '(' else self._css[idx] + self._status = 'instr' + self._from = 'iv' + + elif self._css[idx] == ',': + self._sub_value = self._sub_value.strip() + ',' + + elif self._css[idx] == '\\': + self._sub_value += self.__unicode(idx) + + elif self._css[idx] == ';' or pn: + if len(self._selector) > 0 and self._selector[0] == '@' and data.at_rules.has_key(self._selector[1:]) and data.at_rules[self._selector[1:]] == 'iv': + self._sub_value_arr.append(self._sub_value.strip()) + + self._status = 'is' + + if '@charset' in self._selector: + self._charset = self._sub_value_arr[0] + + elif '@namespace' in self._selector: + self._namespace = ' '.join(self._sub_value_arr) + + elif '@import' in self._selector: + self._import.append(' '.join(self._sub_value_arr)) + + + self._sub_value_arr = [] + self._sub_value = '' + self._selector = '' + self._sel_separate = [] + + else: + self._status = 'ip' + + elif self._css[idx] != '}': + self._sub_value += self._css[idx] + + if (self._css[idx] == '}' or self._css[idx] == ';' or pn) and self._selector != '': + if self._at == '': + self._at = data.DEFAULT_AT + + #case settings + if self.getSetting('lowercase_s'): + self._selector = self._selector.lower() + + self._property = self._property.lower() + + if self._sub_value != '': + self._sub_value_arr.append(self._sub_value) + self._sub_value = '' + + self._value = ' '.join(self._sub_value_arr) + + + self._selector = self._selector.strip() + + valid = self.__property_is_valid(self._property) + + if (not self._invalid_at or self.getSetting('preserve_css')) and (not self.getSetting('discard_invalid_properties') or valid): + self.__css_add_property(self._at, self._selector, self._property, self._value) + self.__add_token(data.VALUE, self._value) + + if not valid: + if self.getSetting('discard_invalid_properties'): + self.log('Removed invalid property: ' + self._property, 'Warning') + + else: + self.log('Invalid property in ' + self.getSetting('css_level').upper() + ': ' + self._property, 'Warning') + + self._property = ''; + self._sub_value_arr = [] + self._value = '' + + if self._css[idx] == '}': + self.__explode_selectors() + self.__add_token(data.SEL_END, self._selector) + self._status = 'is' + self._invalid_at = False + self._selector = '' + + elif not pn: + self._sub_value += self._css[idx] + + if self._css[idx].isspace(): + if self._sub_value != '': + self._sub_value_arr.append(self._sub_value) + self._sub_value = '' + + return 0 + + def __parseStatus_instr(self, idx): + """ + Parse in String + """ + if self._str_char == ')' and (self._css[idx] == '"' or self._css[idx] == "'") and not self.escaped(self._css, idx): + self._str_in_str = not self._str_in_str + + temp_add = self._css[idx] # ...and no not-escaped backslash at the previous position + if (self._css[idx] == "\n" or self._css[idx] == "\r") and not (self._css[idx-1] == '\\' and not self.escaped(self._css, idx-1)): + temp_add = "\\A " + self.log('Fixed incorrect newline in string', 'Warning') + + if not (self._str_char == ')' and self._css[idx].isspace() and not self._str_in_str): + self._cur_string += temp_add + + if self._css[idx] == self._str_char and not self.escaped(self._css, idx) and not self._str_in_str: + self._status = self._from + regex = re.compile(r'([\s]+)', re.I | re.U | re.S) + if regex.match(self._cur_string) is None and self._property != 'content': + if self._str_char == '"' or self._str_char == "'": + self._cur_string = self._cur_string[1:-1] + + elif len(self._cur_string) > 3 and (self._cur_string[1] == '"' or self._cur_string[1] == "'"): + self._cur_string = self._cur_string[0] + self._cur_string[2:-2] + self._cur_string[-1] + + if self._from == 'iv': + self._sub_value += self._cur_string + + elif self._from == 'is': + self._selector += self._cur_string + + return 0 + + def __parseStatus_ic(self, idx): + """ + Parse css In Comment + """ + if self._css[idx] == '*' and self._css[idx+1] == '/': + self._status = self._from + self.__add_token(data.COMMENT, self._curComment) + self._curComment = '' + return 1 + + else: + self._curComment += self._css[idx] + + return 0 + + def __parseStatus_at(self, idx): + """ + Parse in at-block + """ + if self.__is_token(string, idx): + if self._css[idx] == '/' and self._css[idx+1] == '*': + self._status = 'ic' + self._from = 'at' + return 1 + + elif self._css[i] == '{': + self._status = 'is' + self.__add_token(data.AT_START, self._at) + + elif self._css[i] == ',': + self._at = self._at.strip() + ',' + + elif self._css[i] == '\\': + self._at += self.__unicode(i) + else: + lastpos = len(self._at)-1 + if not (self._at[lastpos].isspace() or self.__is_token(self._at, lastpos) and self._at[lastpos] == ',') and self._css[i].isspace(): + self._at += self._css[i] + + return 0 + + def __explode_selectors(self): + #Explode multiple selectors + if self.getSetting('merge_selectors') == 1: + new_sels = [] + lastpos = 0; + self._sel_separate.append(len(self._selector)) + + for num in xrange(len(self._sel_separate)): + pos = self._sel_separate[num] + if num == (len(self._sel_separate)): #CHECK# + pos += 1 + + new_sels.append(self._selector[lastpos:(pos-lastpos-1)]) + lastpos = pos + + if len(new_sels) > 1: + for selector in new_sels: + self.merge_css_blocks(self._at, selector, self._raw_css[self._at][self._selector]) + + del self._raw_css[self._at][self._selector] + + self._sel_separate = [] + + #Adds a property with value to the existing CSS code + def __css_add_property(self, media, selector, prop, new_val): + if self.getSetting('preserve_css') or new_val.strip() == '': + return + + if not self._raw_css.has_key(media): + self._raw_css[media] = SortedDict() + + if not self._raw_css[media].has_key(selector): + self._raw_css[media][selector] = SortedDict() + + self._added = True + if self._raw_css[media][selector].has_key(prop): + if (self.is_important(self._raw_css[media][selector][prop]) and self.is_important(new_val)) or not self.is_important(self._raw_css[media][selector][prop]): + del self._raw_css[media][selector][prop] + self._raw_css[media][selector][prop] = new_val.strip() + + else: + self._raw_css[media][selector][prop] = new_val.strip() + + #Checks if the next word in a string from pos is a CSS property + def __property_is_next(self, pos): + istring = self._css[pos: len(self._css)] + pos = istring.find(':') + if pos == -1: + return False; + + istring = istring[:pos].strip().lower() + if data.all_properties.has_key(istring): + self.log('Added semicolon to the end of declaration', 'Warning') + return True + + return False; + + #Checks if a property is valid + def __property_is_valid(self, prop): + return (data.all_properties.has_key(prop) and data.all_properties[prop].find(self.getSetting('css_level').upper()) != -1) + + #Adds a token to self._tokens + def __add_token(self, ttype, cssdata, do=False): + if self.getSetting('preserve_css') or do: + if ttype == data.COMMENT: + token = [ttype, cssdata] + else: + token = [ttype, cssdata.strip()] + + self._tokens.append(token) + + #Parse unicode notations and find a replacement character + def __unicode(self, idx): + ##FIX## + return '' + + #Starts parsing from URL + ##USED? + def __parse_from_url(self, url): + try: + if "http" in url.lower() or "https" in url.lower(): + f = urllib.urlopen(url) + else: + f = open(url) + + data = f.read() + return self.parse(data) + finally: + f.close() + + #Checks if there is a token at the current position + def __is_token(self, string, idx): + return (string[idx] in data.tokens and not self.escaped(string, idx)) + + + #Property Methods + def _getOutput(self): + self._output.prepare(self._optimized_css) + return self._output.render + + def _getLog(self): + ret = "" + ks = self._log.keys() + ks.sort() + for line in ks: + for msg in self._log[line]: + ret += "Type: " + msg['t'] + "\n" + ret += "Message: " + msg['m'] + "\n" + ret += "\n" + + return ret + + def _getCSS(self): + return self._css + + + #Properties + Output = property(_getOutput, None) + Log = property(_getLog, None) + CSS = property(_getCSS, None) + + +if __name__ == '__main__': + import sys + tidy = CSSTidy() + f = open(sys.argv[1], "r") + css = f.read() + f.close() + tidy.parse(css) + tidy.Output('file', filename="Stylesheet.min.css") + print tidy.Output() + #print tidy._import \ No newline at end of file diff --git a/compress/filters/csstidy_python/data.py b/compress/filters/csstidy_python/data.py new file mode 100644 index 000000000..bd728cbaa --- /dev/null +++ b/compress/filters/csstidy_python/data.py @@ -0,0 +1,421 @@ +# Various CSS Data for CSSTidy +# +# This file is part of CSSTidy. +# +# CSSTidy is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# CSSTidy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with CSSTidy; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# @license http://opensource.org/licenses/gpl-license.php GNU Public License +# @package csstidy +# @author Florian Schmitz (floele at gmail dot com) 2005 + +AT_START = 1 +AT_END = 2 +SEL_START = 3 +SEL_END = 4 +PROPERTY = 5 +VALUE = 6 +COMMENT = 7 +DEFAULT_AT = 41 + +# All whitespace allowed in CSS +# +# @global array whitespace +# @version 1.0 +whitespace = frozenset([' ',"\n","\t","\r","\x0B"]) + +# All CSS tokens used by csstidy +# +# @global string tokens +# @version 1.0 +tokens = '/@}{;:=\'"(,\\!$%&)#+.<>?[]^`|~' + +# All CSS units (CSS 3 units included) +# +# @see compress_numbers() +# @global array units +# @version 1.0 +units = frozenset(['in','cm','mm','pt','pc','px','rem','em','%','ex','gd','vw','vh','vm','deg','grad','rad','ms','s','khz','hz']) + +# Available at-rules +# +# @global array at_rules +# @version 1.0 +at_rules = {'page':'is', 'font-face':'is', 'charset':'iv', 'import':'iv', 'namespace':'iv', 'media':'at'} + +# Properties that need a value with unit +# +# @todo CSS3 properties +# @see compress_numbers() +# @global array unit_values +# @version 1.2 +unit_values = frozenset(['background', 'background-position', 'border', 'border-top', 'border-right', 'border-bottom', + 'border-left', 'border-width', 'border-top-width', 'border-right-width', 'border-left-width', + 'border-bottom-width', 'bottom', 'border-spacing', 'font-size','height', 'left', 'margin', 'margin-top', + 'margin-right', 'margin-bottom', 'margin-left', 'max-height', 'max-width', 'min-height', 'min-width', + 'outline-width', 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left','position', + 'right', 'top', 'text-indent', 'letter-spacing', 'word-spacing', 'width' + ]) + + +# Properties that allow as value +# +# @todo CSS3 properties +# @see compress_numbers() +# @global array color_values +# @version 1.0 +color_values = frozenset(['background-color', 'border-color', 'border-top-color', 'border-right-color', + 'border-bottom-color', 'border-left-color', 'color', 'outline-color']) + + +# Default values for the background properties +# +# @todo Possibly property names will change during CSS3 development +# @global array background_prop_default +# @see dissolve_short_bg() +# @see merge_bg() +# @version 1.0 +background_prop_default = {} +background_prop_default['background-image'] = 'none' +background_prop_default['background-size'] = 'auto' +background_prop_default['background-repeat'] = 'repeat' +background_prop_default['background-position'] = '0 0' +background_prop_default['background-attachment'] = 'scroll' +background_prop_default['background-clip'] = 'border' +background_prop_default['background-origin'] = 'padding' +background_prop_default['background-color'] = 'transparent' + +# A list of non-W3C color names which get replaced by their hex-codes +# +# @global array replace_colors +# @see cut_color() +# @version 1.0 +replace_colors = {} +replace_colors['aliceblue'] = '#F0F8FF' +replace_colors['antiquewhite'] = '#FAEBD7' +replace_colors['aquamarine'] = '#7FFFD4' +replace_colors['azure'] = '#F0FFFF' +replace_colors['beige'] = '#F5F5DC' +replace_colors['bisque'] = '#FFE4C4' +replace_colors['blanchedalmond'] = '#FFEBCD' +replace_colors['blueviolet'] = '#8A2BE2' +replace_colors['brown'] = '#A52A2A' +replace_colors['burlywood'] = '#DEB887' +replace_colors['cadetblue'] = '#5F9EA0' +replace_colors['chartreuse'] = '#7FFF00' +replace_colors['chocolate'] = '#D2691E' +replace_colors['coral'] = '#FF7F50' +replace_colors['cornflowerblue'] = '#6495ED' +replace_colors['cornsilk'] = '#FFF8DC' +replace_colors['crimson'] = '#DC143C' +replace_colors['cyan'] = '#00FFFF' +replace_colors['darkblue'] = '#00008B' +replace_colors['darkcyan'] = '#008B8B' +replace_colors['darkgoldenrod'] = '#B8860B' +replace_colors['darkgray'] = '#A9A9A9' +replace_colors['darkgreen'] = '#006400' +replace_colors['darkkhaki'] = '#BDB76B' +replace_colors['darkmagenta'] = '#8B008B' +replace_colors['darkolivegreen'] = '#556B2F' +replace_colors['darkorange'] = '#FF8C00' +replace_colors['darkorchid'] = '#9932CC' +replace_colors['darkred'] = '#8B0000' +replace_colors['darksalmon'] = '#E9967A' +replace_colors['darkseagreen'] = '#8FBC8F' +replace_colors['darkslateblue'] = '#483D8B' +replace_colors['darkslategray'] = '#2F4F4F' +replace_colors['darkturquoise'] = '#00CED1' +replace_colors['darkviolet'] = '#9400D3' +replace_colors['deeppink'] = '#FF1493' +replace_colors['deepskyblue'] = '#00BFFF' +replace_colors['dimgray'] = '#696969' +replace_colors['dodgerblue'] = '#1E90FF' +replace_colors['feldspar'] = '#D19275' +replace_colors['firebrick'] = '#B22222' +replace_colors['floralwhite'] = '#FFFAF0' +replace_colors['forestgreen'] = '#228B22' +replace_colors['gainsboro'] = '#DCDCDC' +replace_colors['ghostwhite'] = '#F8F8FF' +replace_colors['gold'] = '#FFD700' +replace_colors['goldenrod'] = '#DAA520' +replace_colors['greenyellow'] = '#ADFF2F' +replace_colors['honeydew'] = '#F0FFF0' +replace_colors['hotpink'] = '#FF69B4' +replace_colors['indianred'] = '#CD5C5C' +replace_colors['indigo'] = '#4B0082' +replace_colors['ivory'] = '#FFFFF0' +replace_colors['khaki'] = '#F0E68C' +replace_colors['lavender'] = '#E6E6FA' +replace_colors['lavenderblush'] = '#FFF0F5' +replace_colors['lawngreen'] = '#7CFC00' +replace_colors['lemonchiffon'] = '#FFFACD' +replace_colors['lightblue'] = '#ADD8E6' +replace_colors['lightcoral'] = '#F08080' +replace_colors['lightcyan'] = '#E0FFFF' +replace_colors['lightgoldenrodyellow'] = '#FAFAD2' +replace_colors['lightgrey'] = '#D3D3D3' +replace_colors['lightgreen'] = '#90EE90' +replace_colors['lightpink'] = '#FFB6C1' +replace_colors['lightsalmon'] = '#FFA07A' +replace_colors['lightseagreen'] = '#20B2AA' +replace_colors['lightskyblue'] = '#87CEFA' +replace_colors['lightslateblue'] = '#8470FF' +replace_colors['lightslategray'] = '#778899' +replace_colors['lightsteelblue'] = '#B0C4DE' +replace_colors['lightyellow'] = '#FFFFE0' +replace_colors['limegreen'] = '#32CD32' +replace_colors['linen'] = '#FAF0E6' +replace_colors['magenta'] = '#FF00FF' +replace_colors['mediumaquamarine'] = '#66CDAA' +replace_colors['mediumblue'] = '#0000CD' +replace_colors['mediumorchid'] = '#BA55D3' +replace_colors['mediumpurple'] = '#9370D8' +replace_colors['mediumseagreen'] = '#3CB371' +replace_colors['mediumslateblue'] = '#7B68EE' +replace_colors['mediumspringgreen'] = '#00FA9A' +replace_colors['mediumturquoise'] = '#48D1CC' +replace_colors['mediumvioletred'] = '#C71585' +replace_colors['midnightblue'] = '#191970' +replace_colors['mintcream'] = '#F5FFFA' +replace_colors['mistyrose'] = '#FFE4E1' +replace_colors['moccasin'] = '#FFE4B5' +replace_colors['navajowhite'] = '#FFDEAD' +replace_colors['oldlace'] = '#FDF5E6' +replace_colors['olivedrab'] = '#6B8E23' +replace_colors['orangered'] = '#FF4500' +replace_colors['orchid'] = '#DA70D6' +replace_colors['palegoldenrod'] = '#EEE8AA' +replace_colors['palegreen'] = '#98FB98' +replace_colors['paleturquoise'] = '#AFEEEE' +replace_colors['palevioletred'] = '#D87093' +replace_colors['papayawhip'] = '#FFEFD5' +replace_colors['peachpuff'] = '#FFDAB9' +replace_colors['peru'] = '#CD853F' +replace_colors['pink'] = '#FFC0CB' +replace_colors['plum'] = '#DDA0DD' +replace_colors['powderblue'] = '#B0E0E6' +replace_colors['rosybrown'] = '#BC8F8F' +replace_colors['royalblue'] = '#4169E1' +replace_colors['saddlebrown'] = '#8B4513' +replace_colors['salmon'] = '#FA8072' +replace_colors['sandybrown'] = '#F4A460' +replace_colors['seagreen'] = '#2E8B57' +replace_colors['seashell'] = '#FFF5EE' +replace_colors['sienna'] = '#A0522D' +replace_colors['skyblue'] = '#87CEEB' +replace_colors['slateblue'] = '#6A5ACD' +replace_colors['slategray'] = '#708090' +replace_colors['snow'] = '#FFFAFA' +replace_colors['springgreen'] = '#00FF7F' +replace_colors['steelblue'] = '#4682B4' +replace_colors['tan'] = '#D2B48C' +replace_colors['thistle'] = '#D8BFD8' +replace_colors['tomato'] = '#FF6347' +replace_colors['turquoise'] = '#40E0D0' +replace_colors['violet'] = '#EE82EE' +replace_colors['violetred'] = '#D02090' +replace_colors['wheat'] = '#F5DEB3' +replace_colors['whitesmoke'] = '#F5F5F5' +replace_colors['yellowgreen'] = '#9ACD32' + +#A list of optimized colors +optimize_colors = {} +optimize_colors['black'] = '#000' +optimize_colors['fuchsia'] = '#F0F' +optimize_colors['white'] = '#FFF' +optimize_colors['yellow'] = '#FF0' +optimize_colors['cyan'] = '#0FF' +optimize_colors['magenta'] = '#F0F' +optimize_colors['lightslategray'] = '#789' + +optimize_colors['#800000'] = 'maroon' +optimize_colors['#FFA500'] = 'orange' +optimize_colors['#808000'] = 'olive' +optimize_colors['#800080'] = 'purple' +optimize_colors['#008000'] = 'green' +optimize_colors['#000080'] = 'navy' +optimize_colors['#008080'] = 'teal' +optimize_colors['#C0C0C0'] = 'silver' +optimize_colors['#808080'] = 'gray' +optimize_colors['#4B0082'] = 'indigo' +optimize_colors['#FFD700'] = 'gold' +optimize_colors['#A52A2A'] = 'brown' +optimize_colors['#00FFFF'] = 'cyan' +optimize_colors['#EE82EE'] = 'violet' +optimize_colors['#DA70D6'] = 'orchid' +optimize_colors['#FFE4C4'] = 'bisque' +optimize_colors['#F0E68C'] = 'khaki' +optimize_colors['#F5DEB3'] = 'wheat' +optimize_colors['#FF7F50'] = 'coral' +optimize_colors['#F5F5DC'] = 'beige' +optimize_colors['#F0FFFF'] = 'azure' +optimize_colors['#A0522D'] = 'sienna' +optimize_colors['#CD853F'] = 'peru' +optimize_colors['#FFFFF0'] = 'ivory' +optimize_colors['#DDA0DD'] = 'plum' +optimize_colors['#D2B48C'] = 'tan' +optimize_colors['#FFC0CB'] = 'pink' +optimize_colors['#FFFAFA'] = 'snow' +optimize_colors['#FA8072'] = 'salmon' +optimize_colors['#FF6347'] = 'tomato' +optimize_colors['#FAF0E6'] = 'linen' +optimize_colors['#F00'] = 'red' + + +# A list of all shorthand properties that are devided into four properties and/or have four subvalues +# +# @global array shorthands +# @todo Are there new ones in CSS3? +# @see dissolve_4value_shorthands() +# @see merge_4value_shorthands() +# @version 1.0 +shorthands = {} +shorthands['border-color'] = ['border-top-color','border-right-color','border-bottom-color','border-left-color'] +shorthands['border-style'] = ['border-top-style','border-right-style','border-bottom-style','border-left-style'] +shorthands['border-width'] = ['border-top-width','border-right-width','border-bottom-width','border-left-width'] +shorthands['margin'] = ['margin-top','margin-right','margin-bottom','margin-left'] +shorthands['padding'] = ['padding-top','padding-right','padding-bottom','padding-left'] +shorthands['-moz-border-radius'] = 0 + +# All CSS Properties. Needed for csstidy::property_is_next() +# +# @global array all_properties +# @todo Add CSS3 properties +# @version 1.0 +# @see csstidy::property_is_next() +all_properties = {} +all_properties['background'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['background-color'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['background-image'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['background-repeat'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['background-attachment'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['background-position'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-top'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-right'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-bottom'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-left'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-color'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-top-color'] = 'CSS2.0,CSS2.1' +all_properties['border-bottom-color'] = 'CSS2.0,CSS2.1' +all_properties['border-left-color'] = 'CSS2.0,CSS2.1' +all_properties['border-right-color'] = 'CSS2.0,CSS2.1' +all_properties['border-style'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-top-style'] = 'CSS2.0,CSS2.1' +all_properties['border-right-style'] = 'CSS2.0,CSS2.1' +all_properties['border-left-style'] = 'CSS2.0,CSS2.1' +all_properties['border-bottom-style'] = 'CSS2.0,CSS2.1' +all_properties['border-width'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-top-width'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-right-width'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-left-width'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-bottom-width'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['border-collapse'] = 'CSS2.0,CSS2.1' +all_properties['border-spacing'] = 'CSS2.0,CSS2.1' +all_properties['bottom'] = 'CSS2.0,CSS2.1' +all_properties['caption-side'] = 'CSS2.0,CSS2.1' +all_properties['content'] = 'CSS2.0,CSS2.1' +all_properties['clear'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['clip'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['color'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['counter-reset'] = 'CSS2.0,CSS2.1' +all_properties['counter-increment'] = 'CSS2.0,CSS2.1' +all_properties['cursor'] = 'CSS2.0,CSS2.1' +all_properties['empty-cells'] = 'CSS2.0,CSS2.1' +all_properties['display'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['direction'] = 'CSS2.0,CSS2.1' +all_properties['float'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['font'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['font-family'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['font-style'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['font-variant'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['font-weight'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['font-stretch'] = 'CSS2.0' +all_properties['font-size-adjust'] = 'CSS2.0' +all_properties['font-size'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['height'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['left'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['line-height'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['list-style'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['list-style-type'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['list-style-image'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['list-style-position'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['margin'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['margin-top'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['margin-right'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['margin-bottom'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['margin-left'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['marks'] = 'CSS1.0,CSS2.0' +all_properties['marker-offset'] = 'CSS2.0' +all_properties['max-height'] = 'CSS2.0,CSS2.1' +all_properties['max-width'] = 'CSS2.0,CSS2.1' +all_properties['min-height'] = 'CSS2.0,CSS2.1' +all_properties['min-width'] = 'CSS2.0,CSS2.1' +all_properties['overflow'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['orphans'] = 'CSS2.0,CSS2.1' +all_properties['outline'] = 'CSS2.0,CSS2.1' +all_properties['outline-width'] = 'CSS2.0,CSS2.1' +all_properties['outline-style'] = 'CSS2.0,CSS2.1' +all_properties['outline-color'] = 'CSS2.0,CSS2.1' +all_properties['padding'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['padding-top'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['padding-right'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['padding-bottom'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['padding-left'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['page-break-before'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['page-break-after'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['page-break-inside'] = 'CSS2.0,CSS2.1' +all_properties['page'] = 'CSS2.0' +all_properties['position'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['quotes'] = 'CSS2.0,CSS2.1' +all_properties['right'] = 'CSS2.0,CSS2.1' +all_properties['size'] = 'CSS1.0,CSS2.0' +all_properties['speak-header'] = 'CSS2.0,CSS2.1' +all_properties['table-layout'] = 'CSS2.0,CSS2.1' +all_properties['top'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['text-indent'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['text-align'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['text-decoration'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['text-shadow'] = 'CSS2.0' +all_properties['letter-spacing'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['word-spacing'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['text-transform'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['white-space'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['unicode-bidi'] = 'CSS2.0,CSS2.1' +all_properties['vertical-align'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['visibility'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['width'] = 'CSS1.0,CSS2.0,CSS2.1' +all_properties['widows'] = 'CSS2.0,CSS2.1' +all_properties['z-index'] = 'CSS1.0,CSS2.0,CSS2.1' + +# Speech # +all_properties['volume'] = 'CSS2.0,CSS2.1' +all_properties['speak'] = 'CSS2.0,CSS2.1' +all_properties['pause'] = 'CSS2.0,CSS2.1' +all_properties['pause-before'] = 'CSS2.0,CSS2.1' +all_properties['pause-after'] = 'CSS2.0,CSS2.1' +all_properties['cue'] = 'CSS2.0,CSS2.1' +all_properties['cue-before'] = 'CSS2.0,CSS2.1' +all_properties['cue-after'] = 'CSS2.0,CSS2.1' +all_properties['play-during'] = 'CSS2.0,CSS2.1' +all_properties['azimuth'] = 'CSS2.0,CSS2.1' +all_properties['elevation'] = 'CSS2.0,CSS2.1' +all_properties['speech-rate'] = 'CSS2.0,CSS2.1' +all_properties['voice-family'] = 'CSS2.0,CSS2.1' +all_properties['pitch'] = 'CSS2.0,CSS2.1' +all_properties['pitch-range'] = 'CSS2.0,CSS2.1' +all_properties['stress'] = 'CSS2.0,CSS2.1' +all_properties['richness'] = 'CSS2.0,CSS2.1' +all_properties['speak-punctuation'] = 'CSS2.0,CSS2.1' +all_properties['speak-numeral'] = 'CSS2.0,CSS2.1' \ No newline at end of file diff --git a/compress/filters/csstidy_python/optimizer.py b/compress/filters/csstidy_python/optimizer.py new file mode 100644 index 000000000..7cd284cfc --- /dev/null +++ b/compress/filters/csstidy_python/optimizer.py @@ -0,0 +1,383 @@ +# CSSTidy - CSS Optimizer +# +# CSS Optimizer class +# +# This file is part of CSSTidy. +# +# CSSTidy is free software you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation either version 2 of the License, or +# (at your option) any later version. +# +# CSSTidy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with CSSTidy if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# @license http://opensource.org/licenses/gpl-license.php GNU Public License +# @package csstidy +# @author Dj Gilcrease (digitalxero at gmail dot com) 2005-2006 + +import data +from tools import SortedDict + + +class CSSOptimizer(object): + def __init__(self, parser): + #raw_css is a dict + self.parser = parser + self._optimized_css = SortedDict + + +#PUBLIC METHODS + def optimize(self, raw_css): + if self.parser.getSetting('preserve_css'): + return raw_css + + self._optimized_css = raw_css + + if self.parser.getSetting('merge_selectors') == 2: + self.__merge_selectors() + + ##OPTIMIZE## + for media, css in self._optimized_css.iteritems(): + for selector, cssdata in css.iteritems(): + if self.parser.getSetting('optimise_shorthands') >= 1: + cssdata = self.__merge_4value_shorthands(cssdata) + + if self.parser.getSetting('optimise_shorthands') >= 2: + cssdata = self.__merge_bg(cssdata) + + for item, value in cssdata.iteritems(): + value = self.__compress_numbers(item, value) + value = self.__compress_important(value) + + if item in data.color_values and self.parser.getSetting('compress_colors'): + old = value[:] + value = self.__compress_color(value) + if old != value: + self.parser.log('In "' + selector + '" Optimised ' + item + ': Changed ' + old + ' to ' + value, 'Information') + + if item == 'font-weight' and self.parser.getSetting('compress_font-weight'): + if value == 'bold': + value = '700' + self.parser.log('In "' + selector + '" Optimised font-weight: Changed "bold" to "700"', 'Information') + + elif value == 'normal': + value = '400' + self.parser.log('In "' + selector + '" Optimised font-weight: Changed "normal" to "400"', 'Information') + + self._optimized_css[media][selector][item] = value + + + return self._optimized_css + + +#PRIVATE METHODS + def __merge_bg(self, cssdata): + """ + Merges all background properties + @cssdata (dict) is a dictionary of the selector properties + """ + #Max number of background images. CSS3 not yet fully implemented + img = 1 + clr = 1 + bg_img_list = [] + if cssdata.has_key('background-image'): + img = len(cssdata['background-image'].split(',')) + bg_img_list = self.parser.gvw_important(cssdata['background-image']).split(',') + + elif cssdata.has_key('background-color'): + clr = len(cssdata['background-color'].split(',')) + + + number_of_values = max(img, clr, 1) + + new_bg_value = '' + important = '' + + for i in xrange(number_of_values): + for bg_property, default_value in data.background_prop_default.iteritems(): + #Skip if property does not exist + if not cssdata.has_key(bg_property): + continue + + cur_value = cssdata[bg_property] + + #Skip some properties if there is no background image + if (len(bg_img_list) > i and bg_img_list[i] == 'none') and bg_property in frozenset(['background-size', 'background-position', 'background-attachment', 'background-repeat']): + continue + + #Remove !important + if self.parser.is_important(cur_value): + important = ' !important' + cur_value = self.parser.gvw_important(cur_value) + + #Do not add default values + if cur_value == default_value: + continue + + temp = cur_value.split(',') + + if len(temp) > i: + if bg_property == 'background-size': + new_bg_value += '(' + temp[i] + ') ' + + else: + new_bg_value += temp[i] + ' ' + + new_bg_value = new_bg_value.strip() + if i != (number_of_values-1): + new_bg_value += ',' + + #Delete all background-properties + for bg_property, default_value in data.background_prop_default.iteritems(): + try: + del cssdata[bg_property] + except: + pass + + #Add new background property + if new_bg_value != '': + cssdata['background'] = new_bg_value + important + + return cssdata + + def __merge_4value_shorthands(self, cssdata): + """ + Merges Shorthand properties again, the opposite of dissolve_4value_shorthands() + @cssdata (dict) is a dictionary of the selector properties + """ + for key, value in data.shorthands.iteritems(): + important = '' + if value != 0 and cssdata.has_key(value[0]) and cssdata.has_key(value[1]) and cssdata.has_key(value[2]) and cssdata.has_key(value[3]): + cssdata[key] = '' + + for i in xrange(4): + val = cssdata[value[i]] + if self.parser.is_important(val): + important = '!important' + cssdata[key] += self.parser.gvw_important(val) + ' ' + + else: + cssdata[key] += val + ' ' + + del cssdata[value[i]] + if cssdata.has_key(key): + cssdata[key] = self.__shorthand(cssdata[key] + important.strip()) + + return cssdata + + + def __merge_selectors(self): + """ + Merges selectors with same properties. Example: a{color:red} b{color:red} . a,b{color:red} + Very basic and has at least one bug. Hopefully there is a replacement soon. + @selector_one (string) is the current selector + @value_one (dict) is a dictionary of the selector properties + Note: Currently is the elements of a selector are identical, but in a different order, they are not merged + """ + + ##OPTIMIZE## + ##FIX## + + raw_css = self._optimized_css.copy() + delete = [] + add = SortedDict() + for media, css in raw_css.iteritems(): + for selector_one, value_one in css.iteritems(): + newsel = selector_one + + for selector_two, value_two in css.iteritems(): + if selector_one == selector_two: + #We need to skip self + continue + + if value_one == value_two: + #Ok, we need to merge these two selectors + newsel += ', ' + selector_two + delete.append((media, selector_two)) + + + if not add.has_key(media): + add[media] = SortedDict() + + add[media][newsel] = value_one + delete.append((media, selector_one)) + + for item in delete: + try: + del self._optimized_css[item[0]][item[1]] + except: + #Must have already been deleted + continue + + for media, css in add.iteritems(): + self._optimized_css[media].update(css) + + + + def __shorthand(self, value): + """ + Compresses shorthand values. Example: margin:1px 1px 1px 1px . margin:1px + @value (string) + """ + + ##FIX## + + important = ''; + if self.parser.is_important(value): + value_list = self.parser.gvw_important(value) + important = '!important' + else: + value_list = value + + ret = value + value_list = value_list.split(' ') + + if len(value_list) == 4: + if value_list[0] == value_list[1] and value_list[0] == value_list[2] and value_list[0] == value_list[3]: + ret = value_list[0] + important + + elif value_list[1] == value_list[3] and value_list[0] == value_list[2]: + ret = value_list[0] + ' ' + value_list[1] + important + + elif value_list[1] == value_list[3]: + ret = value_list[0] + ' ' + value_list[1] + ' ' + value_list[2] + important + + elif len(value_list) == 3: + if value_list[0] == value_list[1] and value_list[0] == value_list[2]: + ret = value_list[0] + important + + elif value_list[0] == value_list[2]: + return value_list[0] + ' ' + value_list[1] + important + + elif len(value_list) == 2: + if value_list[0] == value_list[1]: + ret = value_list[0] + important + + if ret != value: + self.parser.log('Optimised shorthand notation: Changed "' + value + '" to "' + ret + '"', 'Information') + + return ret + + def __compress_important(self, value): + """ + Removes unnecessary whitespace in ! important + @value (string) + """ + if self.parser.is_important(value): + value = self.parser.gvw_important(value) + '!important' + + return value + + def __compress_numbers(self, prop, value): + """ + Compresses numbers (ie. 1.0 becomes 1 or 1.100 becomes 1.1 ) + @value (string) is the posible number to be compressed + """ + + ##FIX## + + value = value.split('/') + + for l in xrange(len(value)): + #continue if no numeric value + if not (len(value[l]) > 0 and (value[l][0].isdigit() or value[l][0] in ('+', '-') )): + continue + + #Fix bad colors + if prop in data.color_values: + value[l] = '#' + value[l] + + is_floatable = False + try: + float(value[l]) + is_floatable = True + except: + pass + + if is_floatable and float(value[l]) == 0: + value[l] = '0' + + elif value[l][0] != '#': + unit_found = False + for unit in data.units: + pos = value[l].lower().find(unit) + if pos != -1 and prop not in data.shorthands: + value[l] = self.__remove_leading_zeros(float(value[l][:pos])) + unit + unit_found = True + break; + + if not unit_found and prop in data.unit_values and prop not in data.shorthands: + value[l] = self.__remove_leading_zeros(float(value[l])) + 'px' + + elif not unit_found and prop not in data.shorthands: + value[l] = self.__remove_leading_zeros(float(value[l])) + + + if len(value) > 1: + return '/'.join(value) + + return value[0] + + def __remove_leading_zeros(self, float_val): + """ + Removes the leading zeros from a float value + @float_val (float) + @returns (string) + """ + #Remove leading zero + if abs(float_val) < 1: + if float_val < 0: + float_val = '-' . str(float_val)[2:] + else: + float_val = str(float_val)[1:] + + return str(float_val) + + def __compress_color(self, color): + """ + Color compression function. Converts all rgb() values to #-values and uses the short-form if possible. Also replaces 4 color names by #-values. + @color (string) the {posible} color to change + """ + + #rgb(0,0,0) . #000000 (or #000 in this case later) + if color[:4].lower() == 'rgb(': + color_tmp = color[4:(len(color)-5)] + color_tmp = color_tmp.split(',') + + for c in color_tmp: + c = c.strip() + if c[:-1] == '%': + c = round((255*color_tmp[i])/100) + + if color_tmp[i] > 255: + color_tmp[i] = 255 + + color = '#' + + for i in xrange(3): + if color_tmp[i] < 16: + color += '0' + str(hex(color_tmp[i])).replace('0x', '') + else: + color += str(hex(color_tmp[i])).replace('0x', '') + + #Fix bad color names + if data.replace_colors.has_key(color.lower()): + color = data.replace_colors[color.lower()] + + #aabbcc . #abc + if len(color) == 7: + color_temp = color.lower() + if color_temp[0] == '#' and color_temp[1] == color_temp[2] and color_temp[3] == color_temp[4] and color_temp[5] == color_temp[6]: + color = '#' + color[1] + color[3] + color[5] + + if data.optimize_colors.has_key(color.lower()): + color = data.optimize_colors[color.lower()] + + return color \ No newline at end of file diff --git a/compress/filters/csstidy_python/output.py b/compress/filters/csstidy_python/output.py new file mode 100644 index 000000000..795a0d050 --- /dev/null +++ b/compress/filters/csstidy_python/output.py @@ -0,0 +1,101 @@ +# CSSTidy - CSS Printer +# +# CSS Printer class +# +# This file is part of CSSTidy. +# +# CSSTidy is free software you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation either version 2 of the License, or +# (at your option) any later version. +# +# CSSTidy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with CSSTidy if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# @license http://opensource.org/licenses/gpl-license.php GNU Public License +# @package csstidy +# @author Dj Gilcrease (digitalxero at gmail dot com) 2005-2006 + +import data + +class CSSPrinter(object): + def __init__(self, parser): + self.parser = parser + self._css = {} + self.__renderMethods = {'string': self.__renderString, 'file': self.__renderFile} + +#PUBLIC METHODS + def prepare(self, css): + self._css = css + + def render(self, output="string", *args, **kwargs): + return self.__renderMethods[output](*args, **kwargs) + +#PRIVATE METHODS + def __renderString(self, *args, **kwargs): + ##OPTIMIZE## + template = self.parser.getSetting('template') + ret = "" + + if template == 'highest_compression': + top_line_end = "" + iner_line_end = "" + bottom_line_end = "" + indent = "" + + elif template == 'high_compression': + top_line_end = "\n" + iner_line_end = "" + bottom_line_end = "\n" + indent = "" + + elif template == 'default': + top_line_end = "\n" + iner_line_end = "\n" + bottom_line_end = "\n\n" + indent = "" + + elif template == 'low_compression': + top_line_end = "\n" + iner_line_end = "\n" + bottom_line_end = "\n\n" + indent = " " + + if self.parser.getSetting('timestamp'): + ret += '/# CSSTidy ' + self.parser.version + ': ' + datetime.now().strftime("%a, %d %b %Y %H:%M:%S +0000") + ' #/' + top_line_end + + for item in self.parser._import: + ret += '@import(' + item + ');' + top_line_end + + for item in self.parser._charset: + ret += '@charset(' + item + ');' + top_line_end + + for item in self.parser._namespace: + ret += '@namespace(' + item + ');' + top_line_end + + for media, css in self._css.iteritems(): + for selector, cssdata in css.iteritems(): + ret += selector + '{' + top_line_end + + for item, value in cssdata.iteritems(): + ret += indent + item + ':' + value + ';' + iner_line_end + + ret += '}' + bottom_line_end + + return ret + + def __renderFile(self, filename=None, *args, **kwargs): + if filename is None: + return self.__renderString() + + try: + f = open(filename, "w") + f.write(self.__renderString()) + finally: + f.close() \ No newline at end of file diff --git a/compress/filters/csstidy_python/tools.py b/compress/filters/csstidy_python/tools.py new file mode 100644 index 000000000..e62faef2c --- /dev/null +++ b/compress/filters/csstidy_python/tools.py @@ -0,0 +1,109 @@ + +class SortedDict(dict): + """ + A dictionary that keeps its keys in the order in which they're inserted. + """ + def __init__(self, data=None): + if data is None: + data = {} + super(SortedDict, self).__init__(data) + if isinstance(data, dict): + self.keyOrder = data.keys() + else: + self.keyOrder = [] + for key, value in data: + if key not in self.keyOrder: + self.keyOrder.append(key) + + def __deepcopy__(self, memo): + from copy import deepcopy + return self.__class__([(key, deepcopy(value, memo)) + for key, value in self.iteritems()]) + + def __setitem__(self, key, value): + super(SortedDict, self).__setitem__(key, value) + if key not in self.keyOrder: + self.keyOrder.append(key) + + def __delitem__(self, key): + super(SortedDict, self).__delitem__(key) + self.keyOrder.remove(key) + + def __iter__(self): + for k in self.keyOrder: + yield k + + def pop(self, k, *args): + result = super(SortedDict, self).pop(k, *args) + try: + self.keyOrder.remove(k) + except ValueError: + # Key wasn't in the dictionary in the first place. No problem. + pass + return result + + def popitem(self): + result = super(SortedDict, self).popitem() + self.keyOrder.remove(result[0]) + return result + + def items(self): + return zip(self.keyOrder, self.values()) + + def iteritems(self): + for key in self.keyOrder: + yield key, super(SortedDict, self).__getitem__(key) + + def keys(self): + return self.keyOrder[:] + + def iterkeys(self): + return iter(self.keyOrder) + + def values(self): + return [super(SortedDict, self).__getitem__(k) for k in self.keyOrder] + + def itervalues(self): + for key in self.keyOrder: + yield super(SortedDict, self).__getitem__(key) + + def update(self, dict_): + for k, v in dict_.items(): + self.__setitem__(k, v) + + def setdefault(self, key, default): + if key not in self.keyOrder: + self.keyOrder.append(key) + return super(SortedDict, self).setdefault(key, default) + + def value_for_index(self, index): + """Returns the value of the item at the given zero-based index.""" + return self[self.keyOrder[index]] + + def insert(self, index, key, value): + """Inserts the key, value pair before the item with the given index.""" + if key in self.keyOrder: + n = self.keyOrder.index(key) + del self.keyOrder[n] + if n < index: + index -= 1 + self.keyOrder.insert(index, key) + super(SortedDict, self).__setitem__(key, value) + + def copy(self): + """Returns a copy of this object.""" + # This way of initializing the copy means it works for subclasses, too. + obj = self.__class__(self) + obj.keyOrder = self.keyOrder[:] + return obj + + def __repr__(self): + """ + Replaces the normal dict.__repr__ with a version that returns the keys + in their sorted order. + """ + return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()]) + + def clear(self): + super(SortedDict, self).clear() + self.keyOrder = [] \ No newline at end of file diff --git a/compress/filters/jsmin/__init__.py b/compress/filters/jsmin/__init__.py new file mode 100644 index 000000000..d22620081 --- /dev/null +++ b/compress/filters/jsmin/__init__.py @@ -0,0 +1,6 @@ +from compress.filters.jsmin.jsmin import jsmin +from compress.filter_base import FilterBase + +class JSMinFilter(FilterBase): + def filter_js(self, js): + return jsmin(js) \ No newline at end of file diff --git a/compress/filters/jsmin/jsmin.py b/compress/filters/jsmin/jsmin.py new file mode 100644 index 000000000..4f9d384f1 --- /dev/null +++ b/compress/filters/jsmin/jsmin.py @@ -0,0 +1,218 @@ +#!/usr/bin/python + +# This code is original from jsmin by Douglas Crockford, it was translated to +# Python by Baruch Even. The original code had the following copyright and +# license. +# +# /* jsmin.c +# 2007-05-22 +# +# Copyright (c) 2002 Douglas Crockford (www.crockford.com) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# The Software shall be used for Good, not Evil. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# */ + +from StringIO import StringIO + +def jsmin(js): + ins = StringIO(js) + outs = StringIO() + JavascriptMinify().minify(ins, outs) + str = outs.getvalue() + if len(str) > 0 and str[0] == '\n': + str = str[1:] + return str + +def isAlphanum(c): + """return true if the character is a letter, digit, underscore, + dollar sign, or non-ASCII character. + """ + return ((c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or + (c >= 'A' and c <= 'Z') or c == '_' or c == '$' or c == '\\' or (c is not None and ord(c) > 126)); + +class UnterminatedComment(Exception): + pass + +class UnterminatedStringLiteral(Exception): + pass + +class UnterminatedRegularExpression(Exception): + pass + +class JavascriptMinify(object): + + def _outA(self): + self.outstream.write(self.theA) + def _outB(self): + self.outstream.write(self.theB) + + def _get(self): + """return the next character from stdin. Watch out for lookahead. If + the character is a control character, translate it to a space or + linefeed. + """ + c = self.theLookahead + self.theLookahead = None + if c == None: + c = self.instream.read(1) + if c >= ' ' or c == '\n': + return c + if c == '': # EOF + return '\000' + if c == '\r': + return '\n' + return ' ' + + def _peek(self): + self.theLookahead = self._get() + return self.theLookahead + + def _next(self): + """get the next character, excluding comments. peek() is used to see + if a '/' is followed by a '/' or '*'. + """ + c = self._get() + if c == '/': + p = self._peek() + if p == '/': + c = self._get() + while c > '\n': + c = self._get() + return c + if p == '*': + c = self._get() + while 1: + c = self._get() + if c == '*': + if self._peek() == '/': + self._get() + return ' ' + if c == '\000': + raise UnterminatedComment() + + return c + + def _action(self, action): + """do something! What you do is determined by the argument: + 1 Output A. Copy B to A. Get the next B. + 2 Copy B to A. Get the next B. (Delete A). + 3 Get the next B. (Delete B). + action treats a string as a single character. Wow! + action recognizes a regular expression if it is preceded by ( or , or =. + """ + if action <= 1: + self._outA() + + if action <= 2: + self.theA = self.theB + if self.theA == "'" or self.theA == '"': + while 1: + self._outA() + self.theA = self._get() + if self.theA == self.theB: + break + if self.theA <= '\n': + raise UnterminatedStringLiteral() + if self.theA == '\\': + self._outA() + self.theA = self._get() + + + if action <= 3: + self.theB = self._next() + if self.theB == '/' and (self.theA == '(' or self.theA == ',' or + self.theA == '=' or self.theA == ':' or + self.theA == '[' or self.theA == '?' or + self.theA == '!' or self.theA == '&' or + self.theA == '|' or self.theA == ';' or + self.theA == '{' or self.theA == '}' or + self.theA == '\n'): + self._outA() + self._outB() + while 1: + self.theA = self._get() + if self.theA == '/': + break + elif self.theA == '\\': + self._outA() + self.theA = self._get() + elif self.theA <= '\n': + raise UnterminatedRegularExpression() + self._outA() + self.theB = self._next() + + + def _jsmin(self): + """Copy the input to the output, deleting the characters which are + insignificant to JavaScript. Comments will be removed. Tabs will be + replaced with spaces. Carriage returns will be replaced with linefeeds. + Most spaces and linefeeds will be removed. + """ + self.theA = '\n' + self._action(3) + + while self.theA != '\000': + if self.theA == ' ': + if isAlphanum(self.theB): + self._action(1) + else: + self._action(2) + elif self.theA == '\n': + if self.theB in ['{', '[', '(', '+', '-']: + self._action(1) + elif self.theB == ' ': + self._action(3) + else: + if isAlphanum(self.theB): + self._action(1) + else: + self._action(2) + else: + if self.theB == ' ': + if isAlphanum(self.theA): + self._action(1) + else: + self._action(3) + elif self.theB == '\n': + if self.theA in ['}', ']', ')', '+', '-', '"', '\'']: + self._action(1) + else: + if isAlphanum(self.theA): + self._action(1) + else: + self._action(3) + else: + self._action(1) + + def minify(self, instream, outstream): + self.instream = instream + self.outstream = outstream + self.theA = '\n' + self.theB = None + self.theLookahead = None + + self._jsmin() + self.instream.close() + +if __name__ == '__main__': + import sys + jsm = JavascriptMinify() + jsm.minify(sys.stdin, sys.stdout) \ No newline at end of file diff --git a/compress/filters/yui/__init__.py b/compress/filters/yui/__init__.py new file mode 100644 index 000000000..1e2e711fd --- /dev/null +++ b/compress/filters/yui/__init__.py @@ -0,0 +1,44 @@ +import subprocess + +from django.conf import settings + +from compress.filter_base import FilterBase, FilterError + +BINARY = getattr(settings, 'COMPRESS_YUI_BINARY', 'java -jar yuicompressor.jar') +CSS_ARGUMENTS = getattr(settings, 'COMPRESS_YUI_CSS_ARGUMENTS', '') +JS_ARGUMENTS = getattr(settings, 'COMPRESS_YUI_JS_ARGUMENTS', '') + +class YUICompressorFilter(FilterBase): + + def filter_common(self, content, type_, arguments): + command = '%s --type=%s %s' % (BINARY, type_, arguments) + + if self.verbose: + command += ' --verbose' + + p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + p.stdin.write(content) + p.stdin.close() + + filtered_css = p.stdout.read() + p.stdout.close() + + err = p.stderr.read() + p.stderr.close() + + if p.wait() != 0: + if not err: + err = 'Unable to apply YUI Compressor filter' + + raise FilterError(err) + + if self.verbose: + print err + + return filtered_css + + def filter_js(self, js): + return self.filter_common(js, 'js', JS_ARGUMENTS) + + def filter_css(self, css): + return self.filter_common(css, 'css', CSS_ARGUMENTS) \ No newline at end of file diff --git a/compress/management/__init__.py b/compress/management/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/compress/management/commands/__init__.py b/compress/management/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/compress/management/commands/synccompress.py b/compress/management/commands/synccompress.py new file mode 100644 index 000000000..6e31d254d --- /dev/null +++ b/compress/management/commands/synccompress.py @@ -0,0 +1,51 @@ +from django.core.management.base import NoArgsCommand +from optparse import make_option + +from django.conf import settings + +class Command(NoArgsCommand): + option_list = NoArgsCommand.option_list + ( + make_option('--force', action='store_true', default=False, help='Force update of all files, even if the source files are older than the current compressed file.'), + make_option('--verbosity', action='store', dest='verbosity', default='1', + type='choice', choices=['0', '1', '2'], + help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), + ) + help = 'Updates and compresses CSS and JavsScript on-demand, without restarting Django' + args = '' + + def handle_noargs(self, **options): + + force = options.get('force', False) + verbosity = int(options.get('verbosity', 1)) + + from compress.utils import needs_update, filter_css, filter_js + + for name, css in settings.COMPRESS_CSS.items(): + u, version = needs_update(css['output_filename'], css['source_filenames']) + + if (force or u) or verbosity >= 2: + msg = 'CSS Group \'%s\'' % name + print msg + print len(msg) * '-' + print "Version: %s" % version + + if force or u: + filter_css(css, verbosity) + + if (force or u) or verbosity >= 2: + print + + for name, js in settings.COMPRESS_JS.items(): + u, version = needs_update(js['output_filename'], js['source_filenames']) + + if (force or u) or verbosity >= 2: + msg = 'JavaScript Group \'%s\'' % name + print msg + print len(msg) * '-' + print "Version: %s" % version + + if force or u: + filter_js(js, verbosity) + + if (force or u) or verbosity >= 2: + print \ No newline at end of file diff --git a/compress/models.py b/compress/models.py new file mode 100644 index 000000000..e69de29bb diff --git a/compress/signals.py b/compress/signals.py new file mode 100644 index 000000000..bd76a76e7 --- /dev/null +++ b/compress/signals.py @@ -0,0 +1,4 @@ +from django.dispatch import Signal + +css_filtered = Signal() +js_filtered = Signal() diff --git a/compress/templates/compress/css.html b/compress/templates/compress/css.html new file mode 100644 index 000000000..68ddbac25 --- /dev/null +++ b/compress/templates/compress/css.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/compress/templates/compress/css_ie.html b/compress/templates/compress/css_ie.html new file mode 100644 index 000000000..80372dc8e --- /dev/null +++ b/compress/templates/compress/css_ie.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/compress/templates/compress/js.html b/compress/templates/compress/js.html new file mode 100644 index 000000000..bfa2b593c --- /dev/null +++ b/compress/templates/compress/js.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/compress/templates/compress/js_ie.html b/compress/templates/compress/js_ie.html new file mode 100644 index 000000000..8235fe2c3 --- /dev/null +++ b/compress/templates/compress/js_ie.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/compress/templatetags/__init__.py b/compress/templatetags/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/compress/templatetags/compressed.py b/compress/templatetags/compressed.py new file mode 100644 index 000000000..2a020099f --- /dev/null +++ b/compress/templatetags/compressed.py @@ -0,0 +1,104 @@ +import os + +from django import template + +from django.conf import settings as django_settings + +from compress.conf import settings +from compress.utils import media_root, media_url, needs_update, filter_css, filter_js, get_output_filename, get_version + +register = template.Library() + +def render_common(template_name, obj, filename, version): + if settings.COMPRESS: + filename = get_output_filename(filename, version) + + context = obj.get('extra_context', {}) + context['url'] = media_url(filename) + + return template.loader.render_to_string(template_name, context) + +def render_css(css, filename, version=None): + return render_common(css.get('template_name', 'compress/css.html'), css, filename, version) + +def render_js(js, filename, version=None): + return render_common(js.get('template_name', 'compress/js.html'), js, filename, version) + +class CompressedCSSNode(template.Node): + def __init__(self, name): + self.name = name + + def render(self, context): + css_name = template.Variable(self.name).resolve(context) + + try: + css = settings.COMPRESS_CSS[css_name] + except KeyError: + return '' # fail silently, do not return anything if an invalid group is specified + + if settings.COMPRESS: + + version = None + + if settings.COMPRESS_AUTO: + u, version = needs_update(css['output_filename'], css['source_filenames']) + if u: + filter_css(css) + + return render_css(css, css['output_filename'], version) + else: + # output source files + r = '' + for source_file in css['source_filenames']: + r += render_css(css, source_file) + + return r + +class CompressedJSNode(template.Node): + def __init__(self, name): + self.name = name + + def render(self, context): + js_name = template.Variable(self.name).resolve(context) + + try: + js = settings.COMPRESS_JS[js_name] + except KeyError: + return '' # fail silently, do not return anything if an invalid group is specified + + if settings.COMPRESS: + + version = None + + if settings.COMPRESS_AUTO: + u, version = needs_update(js['output_filename'], js['source_filenames']) + if u: + filter_js(js) + + return render_js(js, js['output_filename'], version) + else: + # output source files + r = '' + for source_file in js['source_filenames']: + r += render_js(js, source_file) + return r + +#@register.tag +def compressed_css(parser, token): + try: + tag_name, name = token.split_contents() + except ValueError: + raise template.TemplateSyntaxError, '%r requires exactly one argument: the name of a group in the COMPRESS_CSS setting' % token.split_contents()[0] + + return CompressedCSSNode(name) +compressed_css = register.tag(compressed_css) + +#@register.tag +def compressed_js(parser, token): + try: + tag_name, name = token.split_contents() + except ValueError: + raise template.TemplateSyntaxError, '%r requires exactly one argument: the name of a group in the COMPRESS_JS setting' % token.split_contents()[0] + + return CompressedJSNode(name) +compressed_js = register.tag(compressed_js) diff --git a/compress/utils.py b/compress/utils.py new file mode 100644 index 000000000..1e0681f07 --- /dev/null +++ b/compress/utils.py @@ -0,0 +1,130 @@ +import os +import re +import tempfile + +from django.conf import settings as django_settings +from django.utils.http import urlquote +from django.dispatch import dispatcher + +from compress.conf import settings +from compress.signals import css_filtered, js_filtered + +def get_filter(compressor_class): + """ + Convert a string version of a function name to the callable object. + """ + + if not hasattr(compressor_class, '__bases__'): + + try: + compressor_class = compressor_class.encode('ascii') + mod_name, class_name = get_mod_func(compressor_class) + if class_name != '': + compressor_class = getattr(__import__(mod_name, {}, {}, ['']), class_name) + except (ImportError, AttributeError): + raise Exception('Failed to import filter %s' % compressor_class) + + return compressor_class + +def get_mod_func(callback): + """ + Converts 'django.views.news.stories.story_detail' to + ('django.views.news.stories', 'story_detail') + """ + + try: + dot = callback.rindex('.') + except ValueError: + return callback, '' + return callback[:dot], callback[dot+1:] + +def needs_update(output_file, source_files): + """ + Scan the source files for changes and returns True if the output_file needs to be updated. + """ + + mtime = max_mtime(source_files) + version = get_version(mtime) + + compressed_file_full = media_root(get_output_filename(output_file, version)) + + if not os.path.exists(compressed_file_full): + return True, version + + # Check if the output file is outdated + return (os.stat(compressed_file_full).st_mtime < mtime), mtime + +def media_root(filename): + """ + Return the full path to ``filename``. ``filename`` is a relative path name in MEDIA_ROOT + """ + return os.path.join(django_settings.MEDIA_ROOT, filename) + +def media_url(url): + return django_settings.MEDIA_URL + urlquote(url) + +def concat(filenames, separator=''): + """ + Concatenate the files from the list of the ``filenames``, ouput separated with ``separator``. + """ + r = '' + + for filename in filenames: + fd = open(media_root(filename), 'rb') + r += fd.read() + r += separator + fd.close() + + return r + +def max_mtime(files): + return int(max([os.stat(media_root(f)).st_mtime for f in files])) + +def save_file(filename, contents): + fd = open(media_root(filename), 'wb+') + fd.write(contents) + fd.close() + +def get_output_filename(filename, version): + if settings.COMPRESS_VERSION and version is not None: + return filename.replace(settings.COMPRESS_VERSION_PLACEHOLDER, get_version(version)) + else: + return filename.replace(settings.COMPRESS_VERSION_PLACEHOLDER, settings.COMPRESS_VERSION_DEFAULT) + +def get_version(version): + try: + return str(int(version)) + except ValueError: + return str(version) + +def remove_files(path, filename, verbosity=0): + regex = re.compile(r'^%s$' % (os.path.basename(get_output_filename(settings.COMPRESS_VERSION_PLACEHOLDER.join([re.escape(part) for part in filename.split(settings.COMPRESS_VERSION_PLACEHOLDER)]), r'\d+')))) + + for f in os.listdir(path): + if regex.match(f): + if verbosity >= 1: + print "Removing outdated file %s" % f + + os.unlink(os.path.join(path, f)) + +def filter_common(obj, verbosity, filters, attr, separator, signal): + output = concat(obj['source_filenames'], separator) + filename = get_output_filename(obj['output_filename'], get_version(max_mtime(obj['source_filenames']))) + + if settings.COMPRESS_VERSION: + remove_files(os.path.dirname(media_root(filename)), obj['output_filename'], verbosity) + + if verbosity >= 1: + print "Saving %s" % filename + + for f in filters: + output = getattr(get_filter(f)(verbose=(verbosity >= 2)), attr)(output) + + save_file(filename, output) + signal.send(None) + +def filter_css(css, verbosity=0): + return filter_common(css, verbosity, filters=settings.COMPRESS_CSS_FILTERS, attr='filter_css', separator='', signal=css_filtered) + +def filter_js(js, verbosity=0): + return filter_common(js, verbosity, filters=settings.COMPRESS_JS_FILTERS, attr='filter_js', separator=';', signal=js_filtered) diff --git a/feedparser.py b/feedparser.py new file mode 100644 index 000000000..bb802df16 --- /dev/null +++ b/feedparser.py @@ -0,0 +1,2858 @@ +#!/usr/bin/env python +"""Universal feed parser + +Handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds + +Visit http://feedparser.org/ for the latest version +Visit http://feedparser.org/docs/ for the latest documentation + +Required: Python 2.1 or later +Recommended: Python 2.3 or later +Recommended: CJKCodecs and iconv_codec +""" + +__version__ = "4.1"# + "$Revision: 1.92 $"[11:15] + "-cvs" +__license__ = """Copyright (c) 2002-2006, Mark Pilgrim, All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE.""" +__author__ = "Mark Pilgrim " +__contributors__ = ["Jason Diamond ", + "John Beimler ", + "Fazal Majid ", + "Aaron Swartz ", + "Kevin Marks "] +_debug = 0 + +# HTTP "User-Agent" header to send to servers when downloading feeds. +# If you are embedding feedparser in a larger application, you should +# change this to your application name and URL. +USER_AGENT = "UniversalFeedParser/%s +http://feedparser.org/" % __version__ + +# HTTP "Accept" header to send to servers when downloading feeds. If you don't +# want to send an Accept header, set this to None. +ACCEPT_HEADER = "application/atom+xml,application/rdf+xml,application/rss+xml,application/x-netcdf,application/xml;q=0.9,text/xml;q=0.2,*/*;q=0.1" + +# List of preferred XML parsers, by SAX driver name. These will be tried first, +# but if they're not installed, Python will keep searching through its own list +# of pre-installed parsers until it finds one that supports everything we need. +PREFERRED_XML_PARSERS = ["drv_libxml2"] + +# If you want feedparser to automatically run HTML markup through HTML Tidy, set +# this to 1. Requires mxTidy +# or utidylib . +TIDY_MARKUP = 0 + +# List of Python interfaces for HTML Tidy, in order of preference. Only useful +# if TIDY_MARKUP = 1 +PREFERRED_TIDY_INTERFACES = ["uTidy", "mxTidy"] + +# ---------- required modules (should come with any Python distribution) ---------- +import sgmllib, re, sys, copy, urlparse, time, rfc822, types, cgi, urllib, urllib2 +try: + from cStringIO import StringIO as _StringIO +except: + from StringIO import StringIO as _StringIO + +# ---------- optional modules (feedparser will work without these, but with reduced functionality) ---------- + +# gzip is included with most Python distributions, but may not be available if you compiled your own +try: + import gzip +except: + gzip = None +try: + import zlib +except: + zlib = None + +# If a real XML parser is available, feedparser will attempt to use it. feedparser has +# been tested with the built-in SAX parser, PyXML, and libxml2. On platforms where the +# Python distribution does not come with an XML parser (such as Mac OS X 10.2 and some +# versions of FreeBSD), feedparser will quietly fall back on regex-based parsing. +try: + import xml.sax + xml.sax.make_parser(PREFERRED_XML_PARSERS) # test for valid parsers + from xml.sax.saxutils import escape as _xmlescape + _XML_AVAILABLE = 1 +except: + _XML_AVAILABLE = 0 + def _xmlescape(data): + data = data.replace('&', '&') + data = data.replace('>', '>') + data = data.replace('<', '<') + return data + +# base64 support for Atom feeds that contain embedded binary data +try: + import base64, binascii +except: + base64 = binascii = None + +# cjkcodecs and iconv_codec provide support for more character encodings. +# Both are available from http://cjkpython.i18n.org/ +try: + import cjkcodecs.aliases +except: + pass +try: + import iconv_codec +except: + pass + +# chardet library auto-detects character encodings +# Download from http://chardet.feedparser.org/ +try: + import chardet + if _debug: + import chardet.constants + chardet.constants._debug = 1 +except: + chardet = None + +# ---------- don't touch these ---------- +class ThingsNobodyCaresAboutButMe(Exception): pass +class CharacterEncodingOverride(ThingsNobodyCaresAboutButMe): pass +class CharacterEncodingUnknown(ThingsNobodyCaresAboutButMe): pass +class NonXMLContentType(ThingsNobodyCaresAboutButMe): pass +class UndeclaredNamespace(Exception): pass + +sgmllib.tagfind = re.compile('[a-zA-Z][-_.:a-zA-Z0-9]*') +sgmllib.special = re.compile('' % (tag, ''.join([' %s="%s"' % t for t in attrs])), escape=0) + + # match namespaces + if tag.find(':') <> -1: + prefix, suffix = tag.split(':', 1) + else: + prefix, suffix = '', tag + prefix = self.namespacemap.get(prefix, prefix) + if prefix: + prefix = prefix + '_' + + # special hack for better tracking of empty textinput/image elements in illformed feeds + if (not prefix) and tag not in ('title', 'link', 'description', 'name'): + self.intextinput = 0 + if (not prefix) and tag not in ('title', 'link', 'description', 'url', 'href', 'width', 'height'): + self.inimage = 0 + + # call special handler (if defined) or default handler + methodname = '_start_' + prefix + suffix + try: + method = getattr(self, methodname) + return method(attrsD) + except AttributeError: + return self.push(prefix + suffix, 1) + + def unknown_endtag(self, tag): + if _debug: sys.stderr.write('end %s\n' % tag) + # match namespaces + if tag.find(':') <> -1: + prefix, suffix = tag.split(':', 1) + else: + prefix, suffix = '', tag + prefix = self.namespacemap.get(prefix, prefix) + if prefix: + prefix = prefix + '_' + + # call special handler (if defined) or default handler + methodname = '_end_' + prefix + suffix + try: + method = getattr(self, methodname) + method() + except AttributeError: + self.pop(prefix + suffix) + + # track inline content + if self.incontent and self.contentparams.has_key('type') and not self.contentparams.get('type', 'xml').endswith('xml'): + # element declared itself as escaped markup, but it isn't really + self.contentparams['type'] = 'application/xhtml+xml' + if self.incontent and self.contentparams.get('type') == 'application/xhtml+xml': + tag = tag.split(':')[-1] + self.handle_data('' % tag, escape=0) + + # track xml:base and xml:lang going out of scope + if self.basestack: + self.basestack.pop() + if self.basestack and self.basestack[-1]: + self.baseuri = self.basestack[-1] + if self.langstack: + self.langstack.pop() + if self.langstack: # and (self.langstack[-1] is not None): + self.lang = self.langstack[-1] + + def handle_charref(self, ref): + # called for each character reference, e.g. for ' ', ref will be '160' + if not self.elementstack: return + ref = ref.lower() + if ref in ('34', '38', '39', '60', '62', 'x22', 'x26', 'x27', 'x3c', 'x3e'): + text = '&#%s;' % ref + else: + if ref[0] == 'x': + c = int(ref[1:], 16) + else: + c = int(ref) + text = unichr(c).encode('utf-8') + self.elementstack[-1][2].append(text) + + def handle_entityref(self, ref): + # called for each entity reference, e.g. for '©', ref will be 'copy' + if not self.elementstack: return + if _debug: sys.stderr.write('entering handle_entityref with %s\n' % ref) + if ref in ('lt', 'gt', 'quot', 'amp', 'apos'): + text = '&%s;' % ref + else: + # entity resolution graciously donated by Aaron Swartz + def name2cp(k): + import htmlentitydefs + if hasattr(htmlentitydefs, 'name2codepoint'): # requires Python 2.3 + return htmlentitydefs.name2codepoint[k] + k = htmlentitydefs.entitydefs[k] + if k.startswith('&#') and k.endswith(';'): + return int(k[2:-1]) # not in latin-1 + return ord(k) + try: name2cp(ref) + except KeyError: text = '&%s;' % ref + else: text = unichr(name2cp(ref)).encode('utf-8') + self.elementstack[-1][2].append(text) + + def handle_data(self, text, escape=1): + # called for each block of plain text, i.e. outside of any tag and + # not containing any character or entity references + if not self.elementstack: return + if escape and self.contentparams.get('type') == 'application/xhtml+xml': + text = _xmlescape(text) + self.elementstack[-1][2].append(text) + + def handle_comment(self, text): + # called for each comment, e.g. + pass + + def handle_pi(self, text): + # called for each processing instruction, e.g. + pass + + def handle_decl(self, text): + pass + + def parse_declaration(self, i): + # override internal declaration handler to handle CDATA blocks + if _debug: sys.stderr.write('entering parse_declaration\n') + if self.rawdata[i:i+9] == '', i) + if k == -1: k = len(self.rawdata) + self.handle_data(_xmlescape(self.rawdata[i+9:k]), 0) + return k+3 + else: + k = self.rawdata.find('>', i) + return k+1 + + def mapContentType(self, contentType): + contentType = contentType.lower() + if contentType == 'text': + contentType = 'text/plain' + elif contentType == 'html': + contentType = 'text/html' + elif contentType == 'xhtml': + contentType = 'application/xhtml+xml' + return contentType + + def trackNamespace(self, prefix, uri): + loweruri = uri.lower() + if (prefix, loweruri) == (None, 'http://my.netscape.com/rdf/simple/0.9/') and not self.version: + self.version = 'rss090' + if loweruri == 'http://purl.org/rss/1.0/' and not self.version: + self.version = 'rss10' + if loweruri == 'http://www.w3.org/2005/atom' and not self.version: + self.version = 'atom10' + if loweruri.find('backend.userland.com/rss') <> -1: + # match any backend.userland.com namespace + uri = 'http://backend.userland.com/rss' + loweruri = uri + if self._matchnamespaces.has_key(loweruri): + self.namespacemap[prefix] = self._matchnamespaces[loweruri] + self.namespacesInUse[self._matchnamespaces[loweruri]] = uri + else: + self.namespacesInUse[prefix or ''] = uri + + def resolveURI(self, uri): + return _urljoin(self.baseuri or '', uri) + + def decodeEntities(self, element, data): + return data + + def push(self, element, expectingText): + self.elementstack.append([element, expectingText, []]) + + def pop(self, element, stripWhitespace=1): + if not self.elementstack: return + if self.elementstack[-1][0] != element: return + + element, expectingText, pieces = self.elementstack.pop() + output = ''.join(pieces) + if stripWhitespace: + output = output.strip() + if not expectingText: return output + + # decode base64 content + if base64 and self.contentparams.get('base64', 0): + try: + output = base64.decodestring(output) + except binascii.Error: + pass + except binascii.Incomplete: + pass + + # resolve relative URIs + if (element in self.can_be_relative_uri) and output: + output = self.resolveURI(output) + + # decode entities within embedded markup + if not self.contentparams.get('base64', 0): + output = self.decodeEntities(element, output) + + # remove temporary cruft from contentparams + try: + del self.contentparams['mode'] + except KeyError: + pass + try: + del self.contentparams['base64'] + except KeyError: + pass + + # resolve relative URIs within embedded markup + if self.mapContentType(self.contentparams.get('type', 'text/html')) in self.html_types: + if element in self.can_contain_relative_uris: + output = _resolveRelativeURIs(output, self.baseuri, self.encoding) + + # sanitize embedded markup + if self.mapContentType(self.contentparams.get('type', 'text/html')) in self.html_types: + if element in self.can_contain_dangerous_markup: + output = _sanitizeHTML(output, self.encoding) + + if self.encoding and type(output) != type(u''): + try: + output = unicode(output, self.encoding) + except: + pass + + # categories/tags/keywords/whatever are handled in _end_category + if element == 'category': + return output + + # store output in appropriate place(s) + if self.inentry and not self.insource: + if element == 'content': + self.entries[-1].setdefault(element, []) + contentparams = copy.deepcopy(self.contentparams) + contentparams['value'] = output + self.entries[-1][element].append(contentparams) + elif element == 'link': + self.entries[-1][element] = output + if output: + self.entries[-1]['links'][-1]['href'] = output + else: + if element == 'description': + element = 'summary' + self.entries[-1][element] = output + if self.incontent: + contentparams = copy.deepcopy(self.contentparams) + contentparams['value'] = output + self.entries[-1][element + '_detail'] = contentparams + elif (self.infeed or self.insource) and (not self.intextinput) and (not self.inimage): + context = self._getContext() + if element == 'description': + element = 'subtitle' + context[element] = output + if element == 'link': + context['links'][-1]['href'] = output + elif self.incontent: + contentparams = copy.deepcopy(self.contentparams) + contentparams['value'] = output + context[element + '_detail'] = contentparams + return output + + def pushContent(self, tag, attrsD, defaultContentType, expectingText): + self.incontent += 1 + self.contentparams = FeedParserDict({ + 'type': self.mapContentType(attrsD.get('type', defaultContentType)), + 'language': self.lang, + 'base': self.baseuri}) + self.contentparams['base64'] = self._isBase64(attrsD, self.contentparams) + self.push(tag, expectingText) + + def popContent(self, tag): + value = self.pop(tag) + self.incontent -= 1 + self.contentparams.clear() + return value + + def _mapToStandardPrefix(self, name): + colonpos = name.find(':') + if colonpos <> -1: + prefix = name[:colonpos] + suffix = name[colonpos+1:] + prefix = self.namespacemap.get(prefix, prefix) + name = prefix + ':' + suffix + return name + + def _getAttribute(self, attrsD, name): + return attrsD.get(self._mapToStandardPrefix(name)) + + def _isBase64(self, attrsD, contentparams): + if attrsD.get('mode', '') == 'base64': + return 1 + if self.contentparams['type'].startswith('text/'): + return 0 + if self.contentparams['type'].endswith('+xml'): + return 0 + if self.contentparams['type'].endswith('/xml'): + return 0 + return 1 + + def _itsAnHrefDamnIt(self, attrsD): + href = attrsD.get('url', attrsD.get('uri', attrsD.get('href', None))) + if href: + try: + del attrsD['url'] + except KeyError: + pass + try: + del attrsD['uri'] + except KeyError: + pass + attrsD['href'] = href + return attrsD + + def _save(self, key, value): + context = self._getContext() + context.setdefault(key, value) + + def _start_rss(self, attrsD): + versionmap = {'0.91': 'rss091u', + '0.92': 'rss092', + '0.93': 'rss093', + '0.94': 'rss094'} + if not self.version: + attr_version = attrsD.get('version', '') + version = versionmap.get(attr_version) + if version: + self.version = version + elif attr_version.startswith('2.'): + self.version = 'rss20' + else: + self.version = 'rss' + + def _start_dlhottitles(self, attrsD): + self.version = 'hotrss' + + def _start_channel(self, attrsD): + self.infeed = 1 + self._cdf_common(attrsD) + _start_feedinfo = _start_channel + + def _cdf_common(self, attrsD): + if attrsD.has_key('lastmod'): + self._start_modified({}) + self.elementstack[-1][-1] = attrsD['lastmod'] + self._end_modified() + if attrsD.has_key('href'): + self._start_link({}) + self.elementstack[-1][-1] = attrsD['href'] + self._end_link() + + def _start_feed(self, attrsD): + self.infeed = 1 + versionmap = {'0.1': 'atom01', + '0.2': 'atom02', + '0.3': 'atom03'} + if not self.version: + attr_version = attrsD.get('version') + version = versionmap.get(attr_version) + if version: + self.version = version + else: + self.version = 'atom' + + def _end_channel(self): + self.infeed = 0 + _end_feed = _end_channel + + def _start_image(self, attrsD): + self.inimage = 1 + self.push('image', 0) + context = self._getContext() + context.setdefault('image', FeedParserDict()) + + def _end_image(self): + self.pop('image') + self.inimage = 0 + + def _start_textinput(self, attrsD): + self.intextinput = 1 + self.push('textinput', 0) + context = self._getContext() + context.setdefault('textinput', FeedParserDict()) + _start_textInput = _start_textinput + + def _end_textinput(self): + self.pop('textinput') + self.intextinput = 0 + _end_textInput = _end_textinput + + def _start_author(self, attrsD): + self.inauthor = 1 + self.push('author', 1) + _start_managingeditor = _start_author + _start_dc_author = _start_author + _start_dc_creator = _start_author + _start_itunes_author = _start_author + + def _end_author(self): + self.pop('author') + self.inauthor = 0 + self._sync_author_detail() + _end_managingeditor = _end_author + _end_dc_author = _end_author + _end_dc_creator = _end_author + _end_itunes_author = _end_author + + def _start_itunes_owner(self, attrsD): + self.inpublisher = 1 + self.push('publisher', 0) + + def _end_itunes_owner(self): + self.pop('publisher') + self.inpublisher = 0 + self._sync_author_detail('publisher') + + def _start_contributor(self, attrsD): + self.incontributor = 1 + context = self._getContext() + context.setdefault('contributors', []) + context['contributors'].append(FeedParserDict()) + self.push('contributor', 0) + + def _end_contributor(self): + self.pop('contributor') + self.incontributor = 0 + + def _start_dc_contributor(self, attrsD): + self.incontributor = 1 + context = self._getContext() + context.setdefault('contributors', []) + context['contributors'].append(FeedParserDict()) + self.push('name', 0) + + def _end_dc_contributor(self): + self._end_name() + self.incontributor = 0 + + def _start_name(self, attrsD): + self.push('name', 0) + _start_itunes_name = _start_name + + def _end_name(self): + value = self.pop('name') + if self.inpublisher: + self._save_author('name', value, 'publisher') + elif self.inauthor: + self._save_author('name', value) + elif self.incontributor: + self._save_contributor('name', value) + elif self.intextinput: + context = self._getContext() + context['textinput']['name'] = value + _end_itunes_name = _end_name + + def _start_width(self, attrsD): + self.push('width', 0) + + def _end_width(self): + value = self.pop('width') + try: + value = int(value) + except: + value = 0 + if self.inimage: + context = self._getContext() + context['image']['width'] = value + + def _start_height(self, attrsD): + self.push('height', 0) + + def _end_height(self): + value = self.pop('height') + try: + value = int(value) + except: + value = 0 + if self.inimage: + context = self._getContext() + context['image']['height'] = value + + def _start_url(self, attrsD): + self.push('href', 1) + _start_homepage = _start_url + _start_uri = _start_url + + def _end_url(self): + value = self.pop('href') + if self.inauthor: + self._save_author('href', value) + elif self.incontributor: + self._save_contributor('href', value) + elif self.inimage: + context = self._getContext() + context['image']['href'] = value + elif self.intextinput: + context = self._getContext() + context['textinput']['link'] = value + _end_homepage = _end_url + _end_uri = _end_url + + def _start_email(self, attrsD): + self.push('email', 0) + _start_itunes_email = _start_email + + def _end_email(self): + value = self.pop('email') + if self.inpublisher: + self._save_author('email', value, 'publisher') + elif self.inauthor: + self._save_author('email', value) + elif self.incontributor: + self._save_contributor('email', value) + _end_itunes_email = _end_email + + def _getContext(self): + if self.insource: + context = self.sourcedata + elif self.inentry: + context = self.entries[-1] + else: + context = self.feeddata + return context + + def _save_author(self, key, value, prefix='author'): + context = self._getContext() + context.setdefault(prefix + '_detail', FeedParserDict()) + context[prefix + '_detail'][key] = value + self._sync_author_detail() + + def _save_contributor(self, key, value): + context = self._getContext() + context.setdefault('contributors', [FeedParserDict()]) + context['contributors'][-1][key] = value + + def _sync_author_detail(self, key='author'): + context = self._getContext() + detail = context.get('%s_detail' % key) + if detail: + name = detail.get('name') + email = detail.get('email') + if name and email: + context[key] = '%s (%s)' % (name, email) + elif name: + context[key] = name + elif email: + context[key] = email + else: + author = context.get(key) + if not author: return + emailmatch = re.search(r'''(([a-zA-Z0-9\_\-\.\+]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?))''', author) + if not emailmatch: return + email = emailmatch.group(0) + # probably a better way to do the following, but it passes all the tests + author = author.replace(email, '') + author = author.replace('()', '') + author = author.strip() + if author and (author[0] == '('): + author = author[1:] + if author and (author[-1] == ')'): + author = author[:-1] + author = author.strip() + context.setdefault('%s_detail' % key, FeedParserDict()) + context['%s_detail' % key]['name'] = author + context['%s_detail' % key]['email'] = email + + def _start_subtitle(self, attrsD): + self.pushContent('subtitle', attrsD, 'text/plain', 1) + _start_tagline = _start_subtitle + _start_itunes_subtitle = _start_subtitle + + def _end_subtitle(self): + self.popContent('subtitle') + _end_tagline = _end_subtitle + _end_itunes_subtitle = _end_subtitle + + def _start_rights(self, attrsD): + self.pushContent('rights', attrsD, 'text/plain', 1) + _start_dc_rights = _start_rights + _start_copyright = _start_rights + + def _end_rights(self): + self.popContent('rights') + _end_dc_rights = _end_rights + _end_copyright = _end_rights + + def _start_item(self, attrsD): + self.entries.append(FeedParserDict()) + self.push('item', 0) + self.inentry = 1 + self.guidislink = 0 + id = self._getAttribute(attrsD, 'rdf:about') + if id: + context = self._getContext() + context['id'] = id + self._cdf_common(attrsD) + _start_entry = _start_item + _start_product = _start_item + + def _end_item(self): + self.pop('item') + self.inentry = 0 + _end_entry = _end_item + + def _start_dc_language(self, attrsD): + self.push('language', 1) + _start_language = _start_dc_language + + def _end_dc_language(self): + self.lang = self.pop('language') + _end_language = _end_dc_language + + def _start_dc_publisher(self, attrsD): + self.push('publisher', 1) + _start_webmaster = _start_dc_publisher + + def _end_dc_publisher(self): + self.pop('publisher') + self._sync_author_detail('publisher') + _end_webmaster = _end_dc_publisher + + def _start_published(self, attrsD): + self.push('published', 1) + _start_dcterms_issued = _start_published + _start_issued = _start_published + + def _end_published(self): + value = self.pop('published') + self._save('published_parsed', _parse_date(value)) + _end_dcterms_issued = _end_published + _end_issued = _end_published + + def _start_updated(self, attrsD): + self.push('updated', 1) + _start_modified = _start_updated + _start_dcterms_modified = _start_updated + _start_pubdate = _start_updated + _start_dc_date = _start_updated + + def _end_updated(self): + value = self.pop('updated') + parsed_value = _parse_date(value) + self._save('updated_parsed', parsed_value) + _end_modified = _end_updated + _end_dcterms_modified = _end_updated + _end_pubdate = _end_updated + _end_dc_date = _end_updated + + def _start_created(self, attrsD): + self.push('created', 1) + _start_dcterms_created = _start_created + + def _end_created(self): + value = self.pop('created') + self._save('created_parsed', _parse_date(value)) + _end_dcterms_created = _end_created + + def _start_expirationdate(self, attrsD): + self.push('expired', 1) + + def _end_expirationdate(self): + self._save('expired_parsed', _parse_date(self.pop('expired'))) + + def _start_cc_license(self, attrsD): + self.push('license', 1) + value = self._getAttribute(attrsD, 'rdf:resource') + if value: + self.elementstack[-1][2].append(value) + self.pop('license') + + def _start_creativecommons_license(self, attrsD): + self.push('license', 1) + + def _end_creativecommons_license(self): + self.pop('license') + + def _addTag(self, term, scheme, label): + context = self._getContext() + tags = context.setdefault('tags', []) + if (not term) and (not scheme) and (not label): return + value = FeedParserDict({'term': term, 'scheme': scheme, 'label': label}) + if value not in tags: + tags.append(FeedParserDict({'term': term, 'scheme': scheme, 'label': label})) + + def _start_category(self, attrsD): + if _debug: sys.stderr.write('entering _start_category with %s\n' % repr(attrsD)) + term = attrsD.get('term') + scheme = attrsD.get('scheme', attrsD.get('domain')) + label = attrsD.get('label') + self._addTag(term, scheme, label) + self.push('category', 1) + _start_dc_subject = _start_category + _start_keywords = _start_category + + def _end_itunes_keywords(self): + for term in self.pop('itunes_keywords').split(): + self._addTag(term, 'http://www.itunes.com/', None) + + def _start_itunes_category(self, attrsD): + self._addTag(attrsD.get('text'), 'http://www.itunes.com/', None) + self.push('category', 1) + + def _end_category(self): + value = self.pop('category') + if not value: return + context = self._getContext() + tags = context['tags'] + if value and len(tags) and not tags[-1]['term']: + tags[-1]['term'] = value + else: + self._addTag(value, None, None) + _end_dc_subject = _end_category + _end_keywords = _end_category + _end_itunes_category = _end_category + + def _start_cloud(self, attrsD): + self._getContext()['cloud'] = FeedParserDict(attrsD) + + def _start_link(self, attrsD): + attrsD.setdefault('rel', 'alternate') + attrsD.setdefault('type', 'text/html') + attrsD = self._itsAnHrefDamnIt(attrsD) + if attrsD.has_key('href'): + attrsD['href'] = self.resolveURI(attrsD['href']) + expectingText = self.infeed or self.inentry or self.insource + context = self._getContext() + context.setdefault('links', []) + context['links'].append(FeedParserDict(attrsD)) + if attrsD['rel'] == 'enclosure': + self._start_enclosure(attrsD) + if attrsD.has_key('href'): + expectingText = 0 + if (attrsD.get('rel') == 'alternate') and (self.mapContentType(attrsD.get('type')) in self.html_types): + context['link'] = attrsD['href'] + else: + self.push('link', expectingText) + _start_producturl = _start_link + + def _end_link(self): + value = self.pop('link') + context = self._getContext() + if self.intextinput: + context['textinput']['link'] = value + if self.inimage: + context['image']['link'] = value + _end_producturl = _end_link + + def _start_guid(self, attrsD): + self.guidislink = (attrsD.get('ispermalink', 'true') == 'true') + self.push('id', 1) + + def _end_guid(self): + value = self.pop('id') + self._save('guidislink', self.guidislink and not self._getContext().has_key('link')) + if self.guidislink: + # guid acts as link, but only if 'ispermalink' is not present or is 'true', + # and only if the item doesn't already have a link element + self._save('link', value) + + def _start_title(self, attrsD): + self.pushContent('title', attrsD, 'text/plain', self.infeed or self.inentry or self.insource) + _start_dc_title = _start_title + _start_media_title = _start_title + + def _end_title(self): + value = self.popContent('title') + context = self._getContext() + if self.intextinput: + context['textinput']['title'] = value + elif self.inimage: + context['image']['title'] = value + _end_dc_title = _end_title + _end_media_title = _end_title + + def _start_description(self, attrsD): + context = self._getContext() + if context.has_key('summary'): + self._summaryKey = 'content' + self._start_content(attrsD) + else: + self.pushContent('description', attrsD, 'text/html', self.infeed or self.inentry or self.insource) + + def _start_abstract(self, attrsD): + self.pushContent('description', attrsD, 'text/plain', self.infeed or self.inentry or self.insource) + + def _end_description(self): + if self._summaryKey == 'content': + self._end_content() + else: + value = self.popContent('description') + context = self._getContext() + if self.intextinput: + context['textinput']['description'] = value + elif self.inimage: + context['image']['description'] = value + self._summaryKey = None + _end_abstract = _end_description + + def _start_info(self, attrsD): + self.pushContent('info', attrsD, 'text/plain', 1) + _start_feedburner_browserfriendly = _start_info + + def _end_info(self): + self.popContent('info') + _end_feedburner_browserfriendly = _end_info + + def _start_generator(self, attrsD): + if attrsD: + attrsD = self._itsAnHrefDamnIt(attrsD) + if attrsD.has_key('href'): + attrsD['href'] = self.resolveURI(attrsD['href']) + self._getContext()['generator_detail'] = FeedParserDict(attrsD) + self.push('generator', 1) + + def _end_generator(self): + value = self.pop('generator') + context = self._getContext() + if context.has_key('generator_detail'): + context['generator_detail']['name'] = value + + def _start_admin_generatoragent(self, attrsD): + self.push('generator', 1) + value = self._getAttribute(attrsD, 'rdf:resource') + if value: + self.elementstack[-1][2].append(value) + self.pop('generator') + self._getContext()['generator_detail'] = FeedParserDict({'href': value}) + + def _start_admin_errorreportsto(self, attrsD): + self.push('errorreportsto', 1) + value = self._getAttribute(attrsD, 'rdf:resource') + if value: + self.elementstack[-1][2].append(value) + self.pop('errorreportsto') + + def _start_summary(self, attrsD): + context = self._getContext() + if context.has_key('summary'): + self._summaryKey = 'content' + self._start_content(attrsD) + else: + self._summaryKey = 'summary' + self.pushContent(self._summaryKey, attrsD, 'text/plain', 1) + _start_itunes_summary = _start_summary + + def _end_summary(self): + if self._summaryKey == 'content': + self._end_content() + else: + self.popContent(self._summaryKey or 'summary') + self._summaryKey = None + _end_itunes_summary = _end_summary + + def _start_enclosure(self, attrsD): + attrsD = self._itsAnHrefDamnIt(attrsD) + self._getContext().setdefault('enclosures', []).append(FeedParserDict(attrsD)) + href = attrsD.get('href') + if href: + context = self._getContext() + if not context.get('id'): + context['id'] = href + + def _start_source(self, attrsD): + self.insource = 1 + + def _end_source(self): + self.insource = 0 + self._getContext()['source'] = copy.deepcopy(self.sourcedata) + self.sourcedata.clear() + + def _start_content(self, attrsD): + self.pushContent('content', attrsD, 'text/plain', 1) + src = attrsD.get('src') + if src: + self.contentparams['src'] = src + self.push('content', 1) + + def _start_prodlink(self, attrsD): + self.pushContent('content', attrsD, 'text/html', 1) + + def _start_body(self, attrsD): + self.pushContent('content', attrsD, 'application/xhtml+xml', 1) + _start_xhtml_body = _start_body + + def _start_content_encoded(self, attrsD): + self.pushContent('content', attrsD, 'text/html', 1) + _start_fullitem = _start_content_encoded + + def _end_content(self): + copyToDescription = self.mapContentType(self.contentparams.get('type')) in (['text/plain'] + self.html_types) + value = self.popContent('content') + if copyToDescription: + self._save('description', value) + _end_body = _end_content + _end_xhtml_body = _end_content + _end_content_encoded = _end_content + _end_fullitem = _end_content + _end_prodlink = _end_content + + def _start_itunes_image(self, attrsD): + self.push('itunes_image', 0) + self._getContext()['image'] = FeedParserDict({'href': attrsD.get('href')}) + _start_itunes_link = _start_itunes_image + + def _end_itunes_block(self): + value = self.pop('itunes_block', 0) + self._getContext()['itunes_block'] = (value == 'yes') and 1 or 0 + + def _end_itunes_explicit(self): + value = self.pop('itunes_explicit', 0) + self._getContext()['itunes_explicit'] = (value == 'yes') and 1 or 0 + +if _XML_AVAILABLE: + class _StrictFeedParser(_FeedParserMixin, xml.sax.handler.ContentHandler): + def __init__(self, baseuri, baselang, encoding): + if _debug: sys.stderr.write('trying StrictFeedParser\n') + xml.sax.handler.ContentHandler.__init__(self) + _FeedParserMixin.__init__(self, baseuri, baselang, encoding) + self.bozo = 0 + self.exc = None + + def startPrefixMapping(self, prefix, uri): + self.trackNamespace(prefix, uri) + + def startElementNS(self, name, qname, attrs): + namespace, localname = name + lowernamespace = str(namespace or '').lower() + if lowernamespace.find('backend.userland.com/rss') <> -1: + # match any backend.userland.com namespace + namespace = 'http://backend.userland.com/rss' + lowernamespace = namespace + if qname and qname.find(':') > 0: + givenprefix = qname.split(':')[0] + else: + givenprefix = None + prefix = self._matchnamespaces.get(lowernamespace, givenprefix) + if givenprefix and (prefix == None or (prefix == '' and lowernamespace == '')) and not self.namespacesInUse.has_key(givenprefix): + raise UndeclaredNamespace, "'%s' is not associated with a namespace" % givenprefix + if prefix: + localname = prefix + ':' + localname + localname = str(localname).lower() + if _debug: sys.stderr.write('startElementNS: qname = %s, namespace = %s, givenprefix = %s, prefix = %s, attrs = %s, localname = %s\n' % (qname, namespace, givenprefix, prefix, attrs.items(), localname)) + + # qname implementation is horribly broken in Python 2.1 (it + # doesn't report any), and slightly broken in Python 2.2 (it + # doesn't report the xml: namespace). So we match up namespaces + # with a known list first, and then possibly override them with + # the qnames the SAX parser gives us (if indeed it gives us any + # at all). Thanks to MatejC for helping me test this and + # tirelessly telling me that it didn't work yet. + attrsD = {} + for (namespace, attrlocalname), attrvalue in attrs._attrs.items(): + lowernamespace = (namespace or '').lower() + prefix = self._matchnamespaces.get(lowernamespace, '') + if prefix: + attrlocalname = prefix + ':' + attrlocalname + attrsD[str(attrlocalname).lower()] = attrvalue + for qname in attrs.getQNames(): + attrsD[str(qname).lower()] = attrs.getValueByQName(qname) + self.unknown_starttag(localname, attrsD.items()) + + def characters(self, text): + self.handle_data(text) + + def endElementNS(self, name, qname): + namespace, localname = name + lowernamespace = str(namespace or '').lower() + if qname and qname.find(':') > 0: + givenprefix = qname.split(':')[0] + else: + givenprefix = '' + prefix = self._matchnamespaces.get(lowernamespace, givenprefix) + if prefix: + localname = prefix + ':' + localname + localname = str(localname).lower() + self.unknown_endtag(localname) + + def error(self, exc): + self.bozo = 1 + self.exc = exc + + def fatalError(self, exc): + self.error(exc) + raise exc + +class _BaseHTMLProcessor(sgmllib.SGMLParser): + elements_no_end_tag = ['area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', + 'img', 'input', 'isindex', 'link', 'meta', 'param'] + + def __init__(self, encoding): + self.encoding = encoding + if _debug: sys.stderr.write('entering BaseHTMLProcessor, encoding=%s\n' % self.encoding) + sgmllib.SGMLParser.__init__(self) + + def reset(self): + self.pieces = [] + sgmllib.SGMLParser.reset(self) + + def _shorttag_replace(self, match): + tag = match.group(1) + if tag in self.elements_no_end_tag: + return '<' + tag + ' />' + else: + return '<' + tag + '>' + + def feed(self, data): + data = re.compile(r'', self._shorttag_replace, data) # bug [ 1399464 ] Bad regexp for _shorttag_replace + data = re.sub(r'<([^<\s]+?)\s*/>', self._shorttag_replace, data) + data = data.replace(''', "'") + data = data.replace('"', '"') + if self.encoding and type(data) == type(u''): + data = data.encode(self.encoding) + sgmllib.SGMLParser.feed(self, data) + + def normalize_attrs(self, attrs): + # utility method to be called by descendants + attrs = [(k.lower(), v) for k, v in attrs] + attrs = [(k, k in ('rel', 'type') and v.lower() or v) for k, v in attrs] + return attrs + + def unknown_starttag(self, tag, attrs): + # called for each start tag + # attrs is a list of (attr, value) tuples + # e.g. for
, tag='pre', attrs=[('class', 'screen')]
+        if _debug: sys.stderr.write('_BaseHTMLProcessor, unknown_starttag, tag=%s\n' % tag)
+        uattrs = []
+        # thanks to Kevin Marks for this breathtaking hack to deal with (valid) high-bit attribute values in UTF-8 feeds
+        for key, value in attrs:
+            if type(value) != type(u''):
+                value = unicode(value, self.encoding)
+            uattrs.append((unicode(key, self.encoding), value))
+        strattrs = u''.join([u' %s="%s"' % (key, value) for key, value in uattrs]).encode(self.encoding)
+        if tag in self.elements_no_end_tag:
+            self.pieces.append('<%(tag)s%(strattrs)s />' % locals())
+        else:
+            self.pieces.append('<%(tag)s%(strattrs)s>' % locals())
+
+    def unknown_endtag(self, tag):
+        # called for each end tag, e.g. for 
, tag will be 'pre' + # Reconstruct the original end tag. + if tag not in self.elements_no_end_tag: + self.pieces.append("" % locals()) + + def handle_charref(self, ref): + # called for each character reference, e.g. for ' ', ref will be '160' + # Reconstruct the original character reference. + self.pieces.append('&#%(ref)s;' % locals()) + + def handle_entityref(self, ref): + # called for each entity reference, e.g. for '©', ref will be 'copy' + # Reconstruct the original entity reference. + self.pieces.append('&%(ref)s;' % locals()) + + def handle_data(self, text): + # called for each block of plain text, i.e. outside of any tag and + # not containing any character or entity references + # Store the original text verbatim. + if _debug: sys.stderr.write('_BaseHTMLProcessor, handle_text, text=%s\n' % text) + self.pieces.append(text) + + def handle_comment(self, text): + # called for each HTML comment, e.g. + # Reconstruct the original comment. + self.pieces.append('' % locals()) + + def handle_pi(self, text): + # called for each processing instruction, e.g. + # Reconstruct original processing instruction. + self.pieces.append('' % locals()) + + def handle_decl(self, text): + # called for the DOCTYPE, if present, e.g. + # + # Reconstruct original DOCTYPE + self.pieces.append('' % locals()) + + _new_declname_match = re.compile(r'[a-zA-Z][-_.a-zA-Z0-9:]*\s*').match + def _scan_name(self, i, declstartpos): + rawdata = self.rawdata + n = len(rawdata) + if i == n: + return None, -1 + m = self._new_declname_match(rawdata, i) + if m: + s = m.group() + name = s.strip() + if (i + len(s)) == n: + return None, -1 # end of buffer + return name.lower(), m.end() + else: + self.handle_data(rawdata) +# self.updatepos(declstartpos, i) + return None, -1 + + def output(self): + '''Return processed HTML as a single string''' + return ''.join([str(p) for p in self.pieces]) + +class _LooseFeedParser(_FeedParserMixin, _BaseHTMLProcessor): + def __init__(self, baseuri, baselang, encoding): + sgmllib.SGMLParser.__init__(self) + _FeedParserMixin.__init__(self, baseuri, baselang, encoding) + + def decodeEntities(self, element, data): + data = data.replace('<', '<') + data = data.replace('<', '<') + data = data.replace('>', '>') + data = data.replace('>', '>') + data = data.replace('&', '&') + data = data.replace('&', '&') + data = data.replace('"', '"') + data = data.replace('"', '"') + data = data.replace(''', ''') + data = data.replace(''', ''') + if self.contentparams.has_key('type') and not self.contentparams.get('type', 'xml').endswith('xml'): + data = data.replace('<', '<') + data = data.replace('>', '>') + data = data.replace('&', '&') + data = data.replace('"', '"') + data = data.replace(''', "'") + return data + +class _RelativeURIResolver(_BaseHTMLProcessor): + relative_uris = [('a', 'href'), + ('applet', 'codebase'), + ('area', 'href'), + ('blockquote', 'cite'), + ('body', 'background'), + ('del', 'cite'), + ('form', 'action'), + ('frame', 'longdesc'), + ('frame', 'src'), + ('iframe', 'longdesc'), + ('iframe', 'src'), + ('head', 'profile'), + ('img', 'longdesc'), + ('img', 'src'), + ('img', 'usemap'), + ('input', 'src'), + ('input', 'usemap'), + ('ins', 'cite'), + ('link', 'href'), + ('object', 'classid'), + ('object', 'codebase'), + ('object', 'data'), + ('object', 'usemap'), + ('q', 'cite'), + ('script', 'src')] + + def __init__(self, baseuri, encoding): + _BaseHTMLProcessor.__init__(self, encoding) + self.baseuri = baseuri + + def resolveURI(self, uri): + return _urljoin(self.baseuri, uri) + + def unknown_starttag(self, tag, attrs): + attrs = self.normalize_attrs(attrs) + attrs = [(key, ((tag, key) in self.relative_uris) and self.resolveURI(value) or value) for key, value in attrs] + _BaseHTMLProcessor.unknown_starttag(self, tag, attrs) + +def _resolveRelativeURIs(htmlSource, baseURI, encoding): + if _debug: sys.stderr.write('entering _resolveRelativeURIs\n') + p = _RelativeURIResolver(baseURI, encoding) + p.feed(htmlSource) + return p.output() + +class _HTMLSanitizer(_BaseHTMLProcessor): + acceptable_elements = ['a', 'abbr', 'acronym', 'address', 'area', 'b', 'big', + 'blockquote', 'br', 'button', 'caption', 'center', 'cite', 'code', 'col', + 'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt', 'em', 'fieldset', + 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'input', + 'ins', 'kbd', 'label', 'legend', 'li', 'map', 'menu', 'ol', 'optgroup', + 'option', 'p', 'pre', 'q', 's', 'samp', 'select', 'small', 'span', 'strike', + 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', + 'thead', 'tr', 'tt', 'u', 'ul', 'var'] + + acceptable_attributes = ['abbr', 'accept', 'accept-charset', 'accesskey', + 'action', 'align', 'alt', 'axis', 'border', 'cellpadding', 'cellspacing', + 'char', 'charoff', 'charset', 'checked', 'cite', 'class', 'clear', 'cols', + 'colspan', 'color', 'compact', 'coords', 'datetime', 'dir', 'disabled', + 'enctype', 'for', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', + 'id', 'ismap', 'label', 'lang', 'longdesc', 'maxlength', 'media', 'method', + 'multiple', 'name', 'nohref', 'noshade', 'nowrap', 'prompt', 'readonly', + 'rel', 'rev', 'rows', 'rowspan', 'rules', 'scope', 'selected', 'shape', 'size', + 'span', 'src', 'start', 'summary', 'tabindex', 'target', 'title', 'type', + 'usemap', 'valign', 'value', 'vspace', 'width'] + + unacceptable_elements_with_end_tag = ['script', 'applet'] + + def reset(self): + _BaseHTMLProcessor.reset(self) + self.unacceptablestack = 0 + + def unknown_starttag(self, tag, attrs): + if not tag in self.acceptable_elements: + if tag in self.unacceptable_elements_with_end_tag: + self.unacceptablestack += 1 + return + attrs = self.normalize_attrs(attrs) + attrs = [(key, value) for key, value in attrs if key in self.acceptable_attributes] + _BaseHTMLProcessor.unknown_starttag(self, tag, attrs) + + def unknown_endtag(self, tag): + if not tag in self.acceptable_elements: + if tag in self.unacceptable_elements_with_end_tag: + self.unacceptablestack -= 1 + return + _BaseHTMLProcessor.unknown_endtag(self, tag) + + def handle_pi(self, text): + pass + + def handle_decl(self, text): + pass + + def handle_data(self, text): + if not self.unacceptablestack: + _BaseHTMLProcessor.handle_data(self, text) + +def _sanitizeHTML(htmlSource, encoding): + p = _HTMLSanitizer(encoding) + p.feed(htmlSource) + data = p.output() + if TIDY_MARKUP: + # loop through list of preferred Tidy interfaces looking for one that's installed, + # then set up a common _tidy function to wrap the interface-specific API. + _tidy = None + for tidy_interface in PREFERRED_TIDY_INTERFACES: + try: + if tidy_interface == "uTidy": + from tidy import parseString as _utidy + def _tidy(data, **kwargs): + return str(_utidy(data, **kwargs)) + break + elif tidy_interface == "mxTidy": + from mx.Tidy import Tidy as _mxtidy + def _tidy(data, **kwargs): + nerrors, nwarnings, data, errordata = _mxtidy.tidy(data, **kwargs) + return data + break + except: + pass + if _tidy: + utf8 = type(data) == type(u'') + if utf8: + data = data.encode('utf-8') + data = _tidy(data, output_xhtml=1, numeric_entities=1, wrap=0, char_encoding="utf8") + if utf8: + data = unicode(data, 'utf-8') + if data.count(''): + data = data.split('>', 1)[1] + if data.count('= '2.3.3' + assert base64 != None + user, passw = base64.decodestring(req.headers['Authorization'].split(' ')[1]).split(':') + realm = re.findall('realm="([^"]*)"', headers['WWW-Authenticate'])[0] + self.add_password(realm, host, user, passw) + retry = self.http_error_auth_reqed('www-authenticate', host, req, headers) + self.reset_retry_count() + return retry + except: + return self.http_error_default(req, fp, code, msg, headers) + +def _open_resource(url_file_stream_or_string, etag, modified, agent, referrer, handlers): + """URL, filename, or string --> stream + + This function lets you define parsers that take any input source + (URL, pathname to local or network file, or actual data as a string) + and deal with it in a uniform manner. Returned object is guaranteed + to have all the basic stdio read methods (read, readline, readlines). + Just .close() the object when you're done with it. + + If the etag argument is supplied, it will be used as the value of an + If-None-Match request header. + + If the modified argument is supplied, it must be a tuple of 9 integers + as returned by gmtime() in the standard Python time module. This MUST + be in GMT (Greenwich Mean Time). The formatted date/time will be used + as the value of an If-Modified-Since request header. + + If the agent argument is supplied, it will be used as the value of a + User-Agent request header. + + If the referrer argument is supplied, it will be used as the value of a + Referer[sic] request header. + + If handlers is supplied, it is a list of handlers used to build a + urllib2 opener. + """ + + if hasattr(url_file_stream_or_string, 'read'): + return url_file_stream_or_string + + if url_file_stream_or_string == '-': + return sys.stdin + + if urlparse.urlparse(url_file_stream_or_string)[0] in ('http', 'https', 'ftp'): + if not agent: + agent = USER_AGENT + # test for inline user:password for basic auth + auth = None + if base64: + urltype, rest = urllib.splittype(url_file_stream_or_string) + realhost, rest = urllib.splithost(rest) + if realhost: + user_passwd, realhost = urllib.splituser(realhost) + if user_passwd: + url_file_stream_or_string = '%s://%s%s' % (urltype, realhost, rest) + auth = base64.encodestring(user_passwd).strip() + # try to open with urllib2 (to use optional headers) + request = urllib2.Request(url_file_stream_or_string) + request.add_header('User-Agent', agent) + if etag: + request.add_header('If-None-Match', etag) + if modified: + # format into an RFC 1123-compliant timestamp. We can't use + # time.strftime() since the %a and %b directives can be affected + # by the current locale, but RFC 2616 states that dates must be + # in English. + short_weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] + months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + request.add_header('If-Modified-Since', '%s, %02d %s %04d %02d:%02d:%02d GMT' % (short_weekdays[modified[6]], modified[2], months[modified[1] - 1], modified[0], modified[3], modified[4], modified[5])) + if referrer: + request.add_header('Referer', referrer) + if gzip and zlib: + request.add_header('Accept-encoding', 'gzip, deflate') + elif gzip: + request.add_header('Accept-encoding', 'gzip') + elif zlib: + request.add_header('Accept-encoding', 'deflate') + else: + request.add_header('Accept-encoding', '') + if auth: + request.add_header('Authorization', 'Basic %s' % auth) + if ACCEPT_HEADER: + request.add_header('Accept', ACCEPT_HEADER) + request.add_header('A-IM', 'feed') # RFC 3229 support + opener = apply(urllib2.build_opener, tuple([_FeedURLHandler()] + handlers)) + opener.addheaders = [] # RMK - must clear so we only send our custom User-Agent + try: + return opener.open(request) + finally: + opener.close() # JohnD + + # try to open with native open function (if url_file_stream_or_string is a filename) + try: + return open(url_file_stream_or_string) + except: + pass + + # treat url_file_stream_or_string as string + return _StringIO(str(url_file_stream_or_string)) + +_date_handlers = [] +def registerDateHandler(func): + '''Register a date handler function (takes string, returns 9-tuple date in GMT)''' + _date_handlers.insert(0, func) + +# ISO-8601 date parsing routines written by Fazal Majid. +# The ISO 8601 standard is very convoluted and irregular - a full ISO 8601 +# parser is beyond the scope of feedparser and would be a worthwhile addition +# to the Python library. +# A single regular expression cannot parse ISO 8601 date formats into groups +# as the standard is highly irregular (for instance is 030104 2003-01-04 or +# 0301-04-01), so we use templates instead. +# Please note the order in templates is significant because we need a +# greedy match. +_iso8601_tmpl = ['YYYY-?MM-?DD', 'YYYY-MM', 'YYYY-?OOO', + 'YY-?MM-?DD', 'YY-?OOO', 'YYYY', + '-YY-?MM', '-OOO', '-YY', + '--MM-?DD', '--MM', + '---DD', + 'CC', ''] +_iso8601_re = [ + tmpl.replace( + 'YYYY', r'(?P\d{4})').replace( + 'YY', r'(?P\d\d)').replace( + 'MM', r'(?P[01]\d)').replace( + 'DD', r'(?P[0123]\d)').replace( + 'OOO', r'(?P[0123]\d\d)').replace( + 'CC', r'(?P\d\d$)') + + r'(T?(?P\d{2}):(?P\d{2})' + + r'(:(?P\d{2}))?' + + r'(?P[+-](?P\d{2})(:(?P\d{2}))?|Z)?)?' + for tmpl in _iso8601_tmpl] +del tmpl +_iso8601_matches = [re.compile(regex).match for regex in _iso8601_re] +del regex +def _parse_date_iso8601(dateString): + '''Parse a variety of ISO-8601-compatible formats like 20040105''' + m = None + for _iso8601_match in _iso8601_matches: + m = _iso8601_match(dateString) + if m: break + if not m: return + if m.span() == (0, 0): return + params = m.groupdict() + ordinal = params.get('ordinal', 0) + if ordinal: + ordinal = int(ordinal) + else: + ordinal = 0 + year = params.get('year', '--') + if not year or year == '--': + year = time.gmtime()[0] + elif len(year) == 2: + # ISO 8601 assumes current century, i.e. 93 -> 2093, NOT 1993 + year = 100 * int(time.gmtime()[0] / 100) + int(year) + else: + year = int(year) + month = params.get('month', '-') + if not month or month == '-': + # ordinals are NOT normalized by mktime, we simulate them + # by setting month=1, day=ordinal + if ordinal: + month = 1 + else: + month = time.gmtime()[1] + month = int(month) + day = params.get('day', 0) + if not day: + # see above + if ordinal: + day = ordinal + elif params.get('century', 0) or \ + params.get('year', 0) or params.get('month', 0): + day = 1 + else: + day = time.gmtime()[2] + else: + day = int(day) + # special case of the century - is the first year of the 21st century + # 2000 or 2001 ? The debate goes on... + if 'century' in params.keys(): + year = (int(params['century']) - 1) * 100 + 1 + # in ISO 8601 most fields are optional + for field in ['hour', 'minute', 'second', 'tzhour', 'tzmin']: + if not params.get(field, None): + params[field] = 0 + hour = int(params.get('hour', 0)) + minute = int(params.get('minute', 0)) + second = int(params.get('second', 0)) + # weekday is normalized by mktime(), we can ignore it + weekday = 0 + # daylight savings is complex, but not needed for feedparser's purposes + # as time zones, if specified, include mention of whether it is active + # (e.g. PST vs. PDT, CET). Using -1 is implementation-dependent and + # and most implementations have DST bugs + daylight_savings_flag = 0 + tm = [year, month, day, hour, minute, second, weekday, + ordinal, daylight_savings_flag] + # ISO 8601 time zone adjustments + tz = params.get('tz') + if tz and tz != 'Z': + if tz[0] == '-': + tm[3] += int(params.get('tzhour', 0)) + tm[4] += int(params.get('tzmin', 0)) + elif tz[0] == '+': + tm[3] -= int(params.get('tzhour', 0)) + tm[4] -= int(params.get('tzmin', 0)) + else: + return None + # Python's time.mktime() is a wrapper around the ANSI C mktime(3c) + # which is guaranteed to normalize d/m/y/h/m/s. + # Many implementations have bugs, but we'll pretend they don't. + return time.localtime(time.mktime(tm)) +registerDateHandler(_parse_date_iso8601) + +# 8-bit date handling routines written by ytrewq1. +_korean_year = u'\ub144' # b3e2 in euc-kr +_korean_month = u'\uc6d4' # bff9 in euc-kr +_korean_day = u'\uc77c' # c0cf in euc-kr +_korean_am = u'\uc624\uc804' # bfc0 c0fc in euc-kr +_korean_pm = u'\uc624\ud6c4' # bfc0 c8c4 in euc-kr + +_korean_onblog_date_re = \ + re.compile('(\d{4})%s\s+(\d{2})%s\s+(\d{2})%s\s+(\d{2}):(\d{2}):(\d{2})' % \ + (_korean_year, _korean_month, _korean_day)) +_korean_nate_date_re = \ + re.compile(u'(\d{4})-(\d{2})-(\d{2})\s+(%s|%s)\s+(\d{,2}):(\d{,2}):(\d{,2})' % \ + (_korean_am, _korean_pm)) +def _parse_date_onblog(dateString): + '''Parse a string according to the OnBlog 8-bit date format''' + m = _korean_onblog_date_re.match(dateString) + if not m: return + w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s:%(second)s%(zonediff)s' % \ + {'year': m.group(1), 'month': m.group(2), 'day': m.group(3),\ + 'hour': m.group(4), 'minute': m.group(5), 'second': m.group(6),\ + 'zonediff': '+09:00'} + if _debug: sys.stderr.write('OnBlog date parsed as: %s\n' % w3dtfdate) + return _parse_date_w3dtf(w3dtfdate) +registerDateHandler(_parse_date_onblog) + +def _parse_date_nate(dateString): + '''Parse a string according to the Nate 8-bit date format''' + m = _korean_nate_date_re.match(dateString) + if not m: return + hour = int(m.group(5)) + ampm = m.group(4) + if (ampm == _korean_pm): + hour += 12 + hour = str(hour) + if len(hour) == 1: + hour = '0' + hour + w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s:%(second)s%(zonediff)s' % \ + {'year': m.group(1), 'month': m.group(2), 'day': m.group(3),\ + 'hour': hour, 'minute': m.group(6), 'second': m.group(7),\ + 'zonediff': '+09:00'} + if _debug: sys.stderr.write('Nate date parsed as: %s\n' % w3dtfdate) + return _parse_date_w3dtf(w3dtfdate) +registerDateHandler(_parse_date_nate) + +_mssql_date_re = \ + re.compile('(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})(\.\d+)?') +def _parse_date_mssql(dateString): + '''Parse a string according to the MS SQL date format''' + m = _mssql_date_re.match(dateString) + if not m: return + w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s:%(second)s%(zonediff)s' % \ + {'year': m.group(1), 'month': m.group(2), 'day': m.group(3),\ + 'hour': m.group(4), 'minute': m.group(5), 'second': m.group(6),\ + 'zonediff': '+09:00'} + if _debug: sys.stderr.write('MS SQL date parsed as: %s\n' % w3dtfdate) + return _parse_date_w3dtf(w3dtfdate) +registerDateHandler(_parse_date_mssql) + +# Unicode strings for Greek date strings +_greek_months = \ + { \ + u'\u0399\u03b1\u03bd': u'Jan', # c9e1ed in iso-8859-7 + u'\u03a6\u03b5\u03b2': u'Feb', # d6e5e2 in iso-8859-7 + u'\u039c\u03ac\u03ce': u'Mar', # ccdcfe in iso-8859-7 + u'\u039c\u03b1\u03ce': u'Mar', # cce1fe in iso-8859-7 + u'\u0391\u03c0\u03c1': u'Apr', # c1f0f1 in iso-8859-7 + u'\u039c\u03ac\u03b9': u'May', # ccdce9 in iso-8859-7 + u'\u039c\u03b1\u03ca': u'May', # cce1fa in iso-8859-7 + u'\u039c\u03b1\u03b9': u'May', # cce1e9 in iso-8859-7 + u'\u0399\u03bf\u03cd\u03bd': u'Jun', # c9effded in iso-8859-7 + u'\u0399\u03bf\u03bd': u'Jun', # c9efed in iso-8859-7 + u'\u0399\u03bf\u03cd\u03bb': u'Jul', # c9effdeb in iso-8859-7 + u'\u0399\u03bf\u03bb': u'Jul', # c9f9eb in iso-8859-7 + u'\u0391\u03cd\u03b3': u'Aug', # c1fde3 in iso-8859-7 + u'\u0391\u03c5\u03b3': u'Aug', # c1f5e3 in iso-8859-7 + u'\u03a3\u03b5\u03c0': u'Sep', # d3e5f0 in iso-8859-7 + u'\u039f\u03ba\u03c4': u'Oct', # cfeaf4 in iso-8859-7 + u'\u039d\u03bf\u03ad': u'Nov', # cdefdd in iso-8859-7 + u'\u039d\u03bf\u03b5': u'Nov', # cdefe5 in iso-8859-7 + u'\u0394\u03b5\u03ba': u'Dec', # c4e5ea in iso-8859-7 + } + +_greek_wdays = \ + { \ + u'\u039a\u03c5\u03c1': u'Sun', # caf5f1 in iso-8859-7 + u'\u0394\u03b5\u03c5': u'Mon', # c4e5f5 in iso-8859-7 + u'\u03a4\u03c1\u03b9': u'Tue', # d4f1e9 in iso-8859-7 + u'\u03a4\u03b5\u03c4': u'Wed', # d4e5f4 in iso-8859-7 + u'\u03a0\u03b5\u03bc': u'Thu', # d0e5ec in iso-8859-7 + u'\u03a0\u03b1\u03c1': u'Fri', # d0e1f1 in iso-8859-7 + u'\u03a3\u03b1\u03b2': u'Sat', # d3e1e2 in iso-8859-7 + } + +_greek_date_format_re = \ + re.compile(u'([^,]+),\s+(\d{2})\s+([^\s]+)\s+(\d{4})\s+(\d{2}):(\d{2}):(\d{2})\s+([^\s]+)') + +def _parse_date_greek(dateString): + '''Parse a string according to a Greek 8-bit date format.''' + m = _greek_date_format_re.match(dateString) + if not m: return + try: + wday = _greek_wdays[m.group(1)] + month = _greek_months[m.group(3)] + except: + return + rfc822date = '%(wday)s, %(day)s %(month)s %(year)s %(hour)s:%(minute)s:%(second)s %(zonediff)s' % \ + {'wday': wday, 'day': m.group(2), 'month': month, 'year': m.group(4),\ + 'hour': m.group(5), 'minute': m.group(6), 'second': m.group(7),\ + 'zonediff': m.group(8)} + if _debug: sys.stderr.write('Greek date parsed as: %s\n' % rfc822date) + return _parse_date_rfc822(rfc822date) +registerDateHandler(_parse_date_greek) + +# Unicode strings for Hungarian date strings +_hungarian_months = \ + { \ + u'janu\u00e1r': u'01', # e1 in iso-8859-2 + u'febru\u00e1ri': u'02', # e1 in iso-8859-2 + u'm\u00e1rcius': u'03', # e1 in iso-8859-2 + u'\u00e1prilis': u'04', # e1 in iso-8859-2 + u'm\u00e1ujus': u'05', # e1 in iso-8859-2 + u'j\u00fanius': u'06', # fa in iso-8859-2 + u'j\u00falius': u'07', # fa in iso-8859-2 + u'augusztus': u'08', + u'szeptember': u'09', + u'okt\u00f3ber': u'10', # f3 in iso-8859-2 + u'november': u'11', + u'december': u'12', + } + +_hungarian_date_format_re = \ + re.compile(u'(\d{4})-([^-]+)-(\d{,2})T(\d{,2}):(\d{2})((\+|-)(\d{,2}:\d{2}))') + +def _parse_date_hungarian(dateString): + '''Parse a string according to a Hungarian 8-bit date format.''' + m = _hungarian_date_format_re.match(dateString) + if not m: return + try: + month = _hungarian_months[m.group(2)] + day = m.group(3) + if len(day) == 1: + day = '0' + day + hour = m.group(4) + if len(hour) == 1: + hour = '0' + hour + except: + return + w3dtfdate = '%(year)s-%(month)s-%(day)sT%(hour)s:%(minute)s%(zonediff)s' % \ + {'year': m.group(1), 'month': month, 'day': day,\ + 'hour': hour, 'minute': m.group(5),\ + 'zonediff': m.group(6)} + if _debug: sys.stderr.write('Hungarian date parsed as: %s\n' % w3dtfdate) + return _parse_date_w3dtf(w3dtfdate) +registerDateHandler(_parse_date_hungarian) + +# W3DTF-style date parsing adapted from PyXML xml.utils.iso8601, written by +# Drake and licensed under the Python license. Removed all range checking +# for month, day, hour, minute, and second, since mktime will normalize +# these later +def _parse_date_w3dtf(dateString): + def __extract_date(m): + year = int(m.group('year')) + if year < 100: + year = 100 * int(time.gmtime()[0] / 100) + int(year) + if year < 1000: + return 0, 0, 0 + julian = m.group('julian') + if julian: + julian = int(julian) + month = julian / 30 + 1 + day = julian % 30 + 1 + jday = None + while jday != julian: + t = time.mktime((year, month, day, 0, 0, 0, 0, 0, 0)) + jday = time.gmtime(t)[-2] + diff = abs(jday - julian) + if jday > julian: + if diff < day: + day = day - diff + else: + month = month - 1 + day = 31 + elif jday < julian: + if day + diff < 28: + day = day + diff + else: + month = month + 1 + return year, month, day + month = m.group('month') + day = 1 + if month is None: + month = 1 + else: + month = int(month) + day = m.group('day') + if day: + day = int(day) + else: + day = 1 + return year, month, day + + def __extract_time(m): + if not m: + return 0, 0, 0 + hours = m.group('hours') + if not hours: + return 0, 0, 0 + hours = int(hours) + minutes = int(m.group('minutes')) + seconds = m.group('seconds') + if seconds: + seconds = int(seconds) + else: + seconds = 0 + return hours, minutes, seconds + + def __extract_tzd(m): + '''Return the Time Zone Designator as an offset in seconds from UTC.''' + if not m: + return 0 + tzd = m.group('tzd') + if not tzd: + return 0 + if tzd == 'Z': + return 0 + hours = int(m.group('tzdhours')) + minutes = m.group('tzdminutes') + if minutes: + minutes = int(minutes) + else: + minutes = 0 + offset = (hours*60 + minutes) * 60 + if tzd[0] == '+': + return -offset + return offset + + __date_re = ('(?P\d\d\d\d)' + '(?:(?P-|)' + '(?:(?P\d\d\d)' + '|(?P\d\d)(?:(?P=dsep)(?P\d\d))?))?') + __tzd_re = '(?P[-+](?P\d\d)(?::?(?P\d\d))|Z)' + __tzd_rx = re.compile(__tzd_re) + __time_re = ('(?P\d\d)(?P:|)(?P\d\d)' + '(?:(?P=tsep)(?P\d\d(?:[.,]\d+)?))?' + + __tzd_re) + __datetime_re = '%s(?:T%s)?' % (__date_re, __time_re) + __datetime_rx = re.compile(__datetime_re) + m = __datetime_rx.match(dateString) + if (m is None) or (m.group() != dateString): return + gmt = __extract_date(m) + __extract_time(m) + (0, 0, 0) + if gmt[0] == 0: return + return time.gmtime(time.mktime(gmt) + __extract_tzd(m) - time.timezone) +registerDateHandler(_parse_date_w3dtf) + +def _parse_date_rfc822(dateString): + '''Parse an RFC822, RFC1123, RFC2822, or asctime-style date''' + data = dateString.split() + if data[0][-1] in (',', '.') or data[0].lower() in rfc822._daynames: + del data[0] + if len(data) == 4: + s = data[3] + i = s.find('+') + if i > 0: + data[3:] = [s[:i], s[i+1:]] + else: + data.append('') + dateString = " ".join(data) + if len(data) < 5: + dateString += ' 00:00:00 GMT' + tm = rfc822.parsedate_tz(dateString) + if tm: + return time.gmtime(rfc822.mktime_tz(tm)) +# rfc822.py defines several time zones, but we define some extra ones. +# 'ET' is equivalent to 'EST', etc. +_additional_timezones = {'AT': -400, 'ET': -500, 'CT': -600, 'MT': -700, 'PT': -800} +rfc822._timezones.update(_additional_timezones) +registerDateHandler(_parse_date_rfc822) + +def _parse_date(dateString): + '''Parses a variety of date formats into a 9-tuple in GMT''' + for handler in _date_handlers: + try: + date9tuple = handler(dateString) + if not date9tuple: continue + if len(date9tuple) != 9: + if _debug: sys.stderr.write('date handler function must return 9-tuple\n') + raise ValueError + map(int, date9tuple) + return date9tuple + except Exception, e: + if _debug: sys.stderr.write('%s raised %s\n' % (handler.__name__, repr(e))) + pass + return None + +def _getCharacterEncoding(http_headers, xml_data): + '''Get the character encoding of the XML document + + http_headers is a dictionary + xml_data is a raw string (not Unicode) + + This is so much trickier than it sounds, it's not even funny. + According to RFC 3023 ('XML Media Types'), if the HTTP Content-Type + is application/xml, application/*+xml, + application/xml-external-parsed-entity, or application/xml-dtd, + the encoding given in the charset parameter of the HTTP Content-Type + takes precedence over the encoding given in the XML prefix within the + document, and defaults to 'utf-8' if neither are specified. But, if + the HTTP Content-Type is text/xml, text/*+xml, or + text/xml-external-parsed-entity, the encoding given in the XML prefix + within the document is ALWAYS IGNORED and only the encoding given in + the charset parameter of the HTTP Content-Type header should be + respected, and it defaults to 'us-ascii' if not specified. + + Furthermore, discussion on the atom-syntax mailing list with the + author of RFC 3023 leads me to the conclusion that any document + served with a Content-Type of text/* and no charset parameter + must be treated as us-ascii. (We now do this.) And also that it + must always be flagged as non-well-formed. (We now do this too.) + + If Content-Type is unspecified (input was local file or non-HTTP source) + or unrecognized (server just got it totally wrong), then go by the + encoding given in the XML prefix of the document and default to + 'iso-8859-1' as per the HTTP specification (RFC 2616). + + Then, assuming we didn't find a character encoding in the HTTP headers + (and the HTTP Content-type allowed us to look in the body), we need + to sniff the first few bytes of the XML data and try to determine + whether the encoding is ASCII-compatible. Section F of the XML + specification shows the way here: + http://www.w3.org/TR/REC-xml/#sec-guessing-no-ext-info + + If the sniffed encoding is not ASCII-compatible, we need to make it + ASCII compatible so that we can sniff further into the XML declaration + to find the encoding attribute, which will tell us the true encoding. + + Of course, none of this guarantees that we will be able to parse the + feed in the declared character encoding (assuming it was declared + correctly, which many are not). CJKCodecs and iconv_codec help a lot; + you should definitely install them if you can. + http://cjkpython.i18n.org/ + ''' + + def _parseHTTPContentType(content_type): + '''takes HTTP Content-Type header and returns (content type, charset) + + If no charset is specified, returns (content type, '') + If no content type is specified, returns ('', '') + Both return parameters are guaranteed to be lowercase strings + ''' + content_type = content_type or '' + content_type, params = cgi.parse_header(content_type) + return content_type, params.get('charset', '').replace("'", '') + + sniffed_xml_encoding = '' + xml_encoding = '' + true_encoding = '' + http_content_type, http_encoding = _parseHTTPContentType(http_headers.get('content-type')) + # Must sniff for non-ASCII-compatible character encodings before + # searching for XML declaration. This heuristic is defined in + # section F of the XML specification: + # http://www.w3.org/TR/REC-xml/#sec-guessing-no-ext-info + try: + if xml_data[:4] == '\x4c\x6f\xa7\x94': + # EBCDIC + xml_data = _ebcdic_to_ascii(xml_data) + elif xml_data[:4] == '\x00\x3c\x00\x3f': + # UTF-16BE + sniffed_xml_encoding = 'utf-16be' + xml_data = unicode(xml_data, 'utf-16be').encode('utf-8') + elif (len(xml_data) >= 4) and (xml_data[:2] == '\xfe\xff') and (xml_data[2:4] != '\x00\x00'): + # UTF-16BE with BOM + sniffed_xml_encoding = 'utf-16be' + xml_data = unicode(xml_data[2:], 'utf-16be').encode('utf-8') + elif xml_data[:4] == '\x3c\x00\x3f\x00': + # UTF-16LE + sniffed_xml_encoding = 'utf-16le' + xml_data = unicode(xml_data, 'utf-16le').encode('utf-8') + elif (len(xml_data) >= 4) and (xml_data[:2] == '\xff\xfe') and (xml_data[2:4] != '\x00\x00'): + # UTF-16LE with BOM + sniffed_xml_encoding = 'utf-16le' + xml_data = unicode(xml_data[2:], 'utf-16le').encode('utf-8') + elif xml_data[:4] == '\x00\x00\x00\x3c': + # UTF-32BE + sniffed_xml_encoding = 'utf-32be' + xml_data = unicode(xml_data, 'utf-32be').encode('utf-8') + elif xml_data[:4] == '\x3c\x00\x00\x00': + # UTF-32LE + sniffed_xml_encoding = 'utf-32le' + xml_data = unicode(xml_data, 'utf-32le').encode('utf-8') + elif xml_data[:4] == '\x00\x00\xfe\xff': + # UTF-32BE with BOM + sniffed_xml_encoding = 'utf-32be' + xml_data = unicode(xml_data[4:], 'utf-32be').encode('utf-8') + elif xml_data[:4] == '\xff\xfe\x00\x00': + # UTF-32LE with BOM + sniffed_xml_encoding = 'utf-32le' + xml_data = unicode(xml_data[4:], 'utf-32le').encode('utf-8') + elif xml_data[:3] == '\xef\xbb\xbf': + # UTF-8 with BOM + sniffed_xml_encoding = 'utf-8' + xml_data = unicode(xml_data[3:], 'utf-8').encode('utf-8') + else: + # ASCII-compatible + pass + xml_encoding_match = re.compile('^<\?.*encoding=[\'"](.*?)[\'"].*\?>').match(xml_data) + except: + xml_encoding_match = None + if xml_encoding_match: + xml_encoding = xml_encoding_match.groups()[0].lower() + if sniffed_xml_encoding and (xml_encoding in ('iso-10646-ucs-2', 'ucs-2', 'csunicode', 'iso-10646-ucs-4', 'ucs-4', 'csucs4', 'utf-16', 'utf-32', 'utf_16', 'utf_32', 'utf16', 'u16')): + xml_encoding = sniffed_xml_encoding + acceptable_content_type = 0 + application_content_types = ('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity') + text_content_types = ('text/xml', 'text/xml-external-parsed-entity') + if (http_content_type in application_content_types) or \ + (http_content_type.startswith('application/') and http_content_type.endswith('+xml')): + acceptable_content_type = 1 + true_encoding = http_encoding or xml_encoding or 'utf-8' + elif (http_content_type in text_content_types) or \ + (http_content_type.startswith('text/')) and http_content_type.endswith('+xml'): + acceptable_content_type = 1 + true_encoding = http_encoding or 'us-ascii' + elif http_content_type.startswith('text/'): + true_encoding = http_encoding or 'us-ascii' + elif http_headers and (not http_headers.has_key('content-type')): + true_encoding = xml_encoding or 'iso-8859-1' + else: + true_encoding = xml_encoding or 'utf-8' + return true_encoding, http_encoding, xml_encoding, sniffed_xml_encoding, acceptable_content_type + +def _toUTF8(data, encoding): + '''Changes an XML data stream on the fly to specify a new encoding + + data is a raw sequence of bytes (not Unicode) that is presumed to be in %encoding already + encoding is a string recognized by encodings.aliases + ''' + if _debug: sys.stderr.write('entering _toUTF8, trying encoding %s\n' % encoding) + # strip Byte Order Mark (if present) + if (len(data) >= 4) and (data[:2] == '\xfe\xff') and (data[2:4] != '\x00\x00'): + if _debug: + sys.stderr.write('stripping BOM\n') + if encoding != 'utf-16be': + sys.stderr.write('trying utf-16be instead\n') + encoding = 'utf-16be' + data = data[2:] + elif (len(data) >= 4) and (data[:2] == '\xff\xfe') and (data[2:4] != '\x00\x00'): + if _debug: + sys.stderr.write('stripping BOM\n') + if encoding != 'utf-16le': + sys.stderr.write('trying utf-16le instead\n') + encoding = 'utf-16le' + data = data[2:] + elif data[:3] == '\xef\xbb\xbf': + if _debug: + sys.stderr.write('stripping BOM\n') + if encoding != 'utf-8': + sys.stderr.write('trying utf-8 instead\n') + encoding = 'utf-8' + data = data[3:] + elif data[:4] == '\x00\x00\xfe\xff': + if _debug: + sys.stderr.write('stripping BOM\n') + if encoding != 'utf-32be': + sys.stderr.write('trying utf-32be instead\n') + encoding = 'utf-32be' + data = data[4:] + elif data[:4] == '\xff\xfe\x00\x00': + if _debug: + sys.stderr.write('stripping BOM\n') + if encoding != 'utf-32le': + sys.stderr.write('trying utf-32le instead\n') + encoding = 'utf-32le' + data = data[4:] + newdata = unicode(data, encoding) + if _debug: sys.stderr.write('successfully converted %s data to unicode\n' % encoding) + declmatch = re.compile('^<\?xml[^>]*?>') + newdecl = '''''' + if declmatch.search(newdata): + newdata = declmatch.sub(newdecl, newdata) + else: + newdata = newdecl + u'\n' + newdata + return newdata.encode('utf-8') + +def _stripDoctype(data): + '''Strips DOCTYPE from XML document, returns (rss_version, stripped_data) + + rss_version may be 'rss091n' or None + stripped_data is the same XML document, minus the DOCTYPE + ''' + entity_pattern = re.compile(r']*?)>', re.MULTILINE) + data = entity_pattern.sub('', data) + doctype_pattern = re.compile(r']*?)>', re.MULTILINE) + doctype_results = doctype_pattern.findall(data) + doctype = doctype_results and doctype_results[0] or '' + if doctype.lower().count('netscape'): + version = 'rss091n' + else: + version = None + data = doctype_pattern.sub('', data) + return version, data + +def parse(url_file_stream_or_string, etag=None, modified=None, agent=None, referrer=None, handlers=[]): + '''Parse a feed from a URL, file, stream, or string''' + result = FeedParserDict() + result['feed'] = FeedParserDict() + result['entries'] = [] + if _XML_AVAILABLE: + result['bozo'] = 0 + if type(handlers) == types.InstanceType: + handlers = [handlers] + try: + f = _open_resource(url_file_stream_or_string, etag, modified, agent, referrer, handlers) + data = f.read() + except Exception, e: + result['bozo'] = 1 + result['bozo_exception'] = e + data = '' + f = None + + # if feed is gzip-compressed, decompress it + if f and data and hasattr(f, 'headers'): + if gzip and f.headers.get('content-encoding', '') == 'gzip': + try: + data = gzip.GzipFile(fileobj=_StringIO(data)).read() + except Exception, e: + # Some feeds claim to be gzipped but they're not, so + # we get garbage. Ideally, we should re-request the + # feed without the 'Accept-encoding: gzip' header, + # but we don't. + result['bozo'] = 1 + result['bozo_exception'] = e + data = '' + elif zlib and f.headers.get('content-encoding', '') == 'deflate': + try: + data = zlib.decompress(data, -zlib.MAX_WBITS) + except Exception, e: + result['bozo'] = 1 + result['bozo_exception'] = e + data = '' + + # save HTTP headers + if hasattr(f, 'info'): + info = f.info() + result['etag'] = info.getheader('ETag') + last_modified = info.getheader('Last-Modified') + if last_modified: + result['modified'] = _parse_date(last_modified) + if hasattr(f, 'url'): + result['href'] = f.url + result['status'] = 200 + if hasattr(f, 'status'): + result['status'] = f.status + if hasattr(f, 'headers'): + result['headers'] = f.headers.dict + if hasattr(f, 'close'): + f.close() + + # there are four encodings to keep track of: + # - http_encoding is the encoding declared in the Content-Type HTTP header + # - xml_encoding is the encoding declared in the ; changed +# project name +#2.5 - 7/25/2003 - MAP - changed to Python license (all contributors agree); +# removed unnecessary urllib code -- urllib2 should always be available anyway; +# return actual url, status, and full HTTP headers (as result['url'], +# result['status'], and result['headers']) if parsing a remote feed over HTTP -- +# this should pass all the HTTP tests at ; +# added the latest namespace-of-the-week for RSS 2.0 +#2.5.1 - 7/26/2003 - RMK - clear opener.addheaders so we only send our custom +# User-Agent (otherwise urllib2 sends two, which confuses some servers) +#2.5.2 - 7/28/2003 - MAP - entity-decode inline xml properly; added support for +# inline and as used in some RSS 2.0 feeds +#2.5.3 - 8/6/2003 - TvdV - patch to track whether we're inside an image or +# textInput, and also to return the character encoding (if specified) +#2.6 - 1/1/2004 - MAP - dc:author support (MarekK); fixed bug tracking +# nested divs within content (JohnD); fixed missing sys import (JohanS); +# fixed regular expression to capture XML character encoding (Andrei); +# added support for Atom 0.3-style links; fixed bug with textInput tracking; +# added support for cloud (MartijnP); added support for multiple +# category/dc:subject (MartijnP); normalize content model: 'description' gets +# description (which can come from description, summary, or full content if no +# description), 'content' gets dict of base/language/type/value (which can come +# from content:encoded, xhtml:body, content, or fullitem); +# fixed bug matching arbitrary Userland namespaces; added xml:base and xml:lang +# tracking; fixed bug tracking unknown tags; fixed bug tracking content when +# element is not in default namespace (like Pocketsoap feed); +# resolve relative URLs in link, guid, docs, url, comments, wfw:comment, +# wfw:commentRSS; resolve relative URLs within embedded HTML markup in +# description, xhtml:body, content, content:encoded, title, subtitle, +# summary, info, tagline, and copyright; added support for pingback and +# trackback namespaces +#2.7 - 1/5/2004 - MAP - really added support for trackback and pingback +# namespaces, as opposed to 2.6 when I said I did but didn't really; +# sanitize HTML markup within some elements; added mxTidy support (if +# installed) to tidy HTML markup within some elements; fixed indentation +# bug in _parse_date (FazalM); use socket.setdefaulttimeout if available +# (FazalM); universal date parsing and normalization (FazalM): 'created', modified', +# 'issued' are parsed into 9-tuple date format and stored in 'created_parsed', +# 'modified_parsed', and 'issued_parsed'; 'date' is duplicated in 'modified' +# and vice-versa; 'date_parsed' is duplicated in 'modified_parsed' and vice-versa +#2.7.1 - 1/9/2004 - MAP - fixed bug handling " and '. fixed memory +# leak not closing url opener (JohnD); added dc:publisher support (MarekK); +# added admin:errorReportsTo support (MarekK); Python 2.1 dict support (MarekK) +#2.7.4 - 1/14/2004 - MAP - added workaround for improperly formed
tags in +# encoded HTML (skadz); fixed unicode handling in normalize_attrs (ChrisL); +# fixed relative URI processing for guid (skadz); added ICBM support; added +# base64 support +#2.7.5 - 1/15/2004 - MAP - added workaround for malformed DOCTYPE (seen on many +# blogspot.com sites); added _debug variable +#2.7.6 - 1/16/2004 - MAP - fixed bug with StringIO importing +#3.0b3 - 1/23/2004 - MAP - parse entire feed with real XML parser (if available); +# added several new supported namespaces; fixed bug tracking naked markup in +# description; added support for enclosure; added support for source; re-added +# support for cloud which got dropped somehow; added support for expirationDate +#3.0b4 - 1/26/2004 - MAP - fixed xml:lang inheritance; fixed multiple bugs tracking +# xml:base URI, one for documents that don't define one explicitly and one for +# documents that define an outer and an inner xml:base that goes out of scope +# before the end of the document +#3.0b5 - 1/26/2004 - MAP - fixed bug parsing multiple links at feed level +#3.0b6 - 1/27/2004 - MAP - added feed type and version detection, result['version'] +# will be one of SUPPORTED_VERSIONS.keys() or empty string if unrecognized; +# added support for creativeCommons:license and cc:license; added support for +# full Atom content model in title, tagline, info, copyright, summary; fixed bug +# with gzip encoding (not always telling server we support it when we do) +#3.0b7 - 1/28/2004 - MAP - support Atom-style author element in author_detail +# (dictionary of 'name', 'url', 'email'); map author to author_detail if author +# contains name + email address +#3.0b8 - 1/28/2004 - MAP - added support for contributor +#3.0b9 - 1/29/2004 - MAP - fixed check for presence of dict function; added +# support for summary +#3.0b10 - 1/31/2004 - MAP - incorporated ISO-8601 date parsing routines from +# xml.util.iso8601 +#3.0b11 - 2/2/2004 - MAP - added 'rights' to list of elements that can contain +# dangerous markup; fiddled with decodeEntities (not right); liberalized +# date parsing even further +#3.0b12 - 2/6/2004 - MAP - fiddled with decodeEntities (still not right); +# added support to Atom 0.2 subtitle; added support for Atom content model +# in copyright; better sanitizing of dangerous HTML elements with end tags +# (script, frameset) +#3.0b13 - 2/8/2004 - MAP - better handling of empty HTML tags (br, hr, img, +# etc.) in embedded markup, in either HTML or XHTML form (
,
,
) +#3.0b14 - 2/8/2004 - MAP - fixed CDATA handling in non-wellformed feeds under +# Python 2.1 +#3.0b15 - 2/11/2004 - MAP - fixed bug resolving relative links in wfw:commentRSS; +# fixed bug capturing author and contributor URL; fixed bug resolving relative +# links in author and contributor URL; fixed bug resolvin relative links in +# generator URL; added support for recognizing RSS 1.0; passed Simon Fell's +# namespace tests, and included them permanently in the test suite with his +# permission; fixed namespace handling under Python 2.1 +#3.0b16 - 2/12/2004 - MAP - fixed support for RSS 0.90 (broken in b15) +#3.0b17 - 2/13/2004 - MAP - determine character encoding as per RFC 3023 +#3.0b18 - 2/17/2004 - MAP - always map description to summary_detail (Andrei); +# use libxml2 (if available) +#3.0b19 - 3/15/2004 - MAP - fixed bug exploding author information when author +# name was in parentheses; removed ultra-problematic mxTidy support; patch to +# workaround crash in PyXML/expat when encountering invalid entities +# (MarkMoraes); support for textinput/textInput +#3.0b20 - 4/7/2004 - MAP - added CDF support +#3.0b21 - 4/14/2004 - MAP - added Hot RSS support +#3.0b22 - 4/19/2004 - MAP - changed 'channel' to 'feed', 'item' to 'entries' in +# results dict; changed results dict to allow getting values with results.key +# as well as results[key]; work around embedded illformed HTML with half +# a DOCTYPE; work around malformed Content-Type header; if character encoding +# is wrong, try several common ones before falling back to regexes (if this +# works, bozo_exception is set to CharacterEncodingOverride); fixed character +# encoding issues in BaseHTMLProcessor by tracking encoding and converting +# from Unicode to raw strings before feeding data to sgmllib.SGMLParser; +# convert each value in results to Unicode (if possible), even if using +# regex-based parsing +#3.0b23 - 4/21/2004 - MAP - fixed UnicodeDecodeError for feeds that contain +# high-bit characters in attributes in embedded HTML in description (thanks +# Thijs van de Vossen); moved guid, date, and date_parsed to mapped keys in +# FeedParserDict; tweaked FeedParserDict.has_key to return True if asking +# about a mapped key +#3.0fc1 - 4/23/2004 - MAP - made results.entries[0].links[0] and +# results.entries[0].enclosures[0] into FeedParserDict; fixed typo that could +# cause the same encoding to be tried twice (even if it failed the first time); +# fixed DOCTYPE stripping when DOCTYPE contained entity declarations; +# better textinput and image tracking in illformed RSS 1.0 feeds +#3.0fc2 - 5/10/2004 - MAP - added and passed Sam's amp tests; added and passed +# my blink tag tests +#3.0fc3 - 6/18/2004 - MAP - fixed bug in _changeEncodingDeclaration that +# failed to parse utf-16 encoded feeds; made source into a FeedParserDict; +# duplicate admin:generatorAgent/@rdf:resource in generator_detail.url; +# added support for image; refactored parse() fallback logic to try other +# encodings if SAX parsing fails (previously it would only try other encodings +# if re-encoding failed); remove unichr madness in normalize_attrs now that +# we're properly tracking encoding in and out of BaseHTMLProcessor; set +# feed.language from root-level xml:lang; set entry.id from rdf:about; +# send Accept header +#3.0 - 6/21/2004 - MAP - don't try iso-8859-1 (can't distinguish between +# iso-8859-1 and windows-1252 anyway, and most incorrectly marked feeds are +# windows-1252); fixed regression that could cause the same encoding to be +# tried twice (even if it failed the first time) +#3.0.1 - 6/22/2004 - MAP - default to us-ascii for all text/* content types; +# recover from malformed content-type header parameter with no equals sign +# ('text/xml; charset:iso-8859-1') +#3.1 - 6/28/2004 - MAP - added and passed tests for converting HTML entities +# to Unicode equivalents in illformed feeds (aaronsw); added and +# passed tests for converting character entities to Unicode equivalents +# in illformed feeds (aaronsw); test for valid parsers when setting +# XML_AVAILABLE; make version and encoding available when server returns +# a 304; add handlers parameter to pass arbitrary urllib2 handlers (like +# digest auth or proxy support); add code to parse username/password +# out of url and send as basic authentication; expose downloading-related +# exceptions in bozo_exception (aaronsw); added __contains__ method to +# FeedParserDict (aaronsw); added publisher_detail (aaronsw) +#3.2 - 7/3/2004 - MAP - use cjkcodecs and iconv_codec if available; always +# convert feed to UTF-8 before passing to XML parser; completely revamped +# logic for determining character encoding and attempting XML parsing +# (much faster); increased default timeout to 20 seconds; test for presence +# of Location header on redirects; added tests for many alternate character +# encodings; support various EBCDIC encodings; support UTF-16BE and +# UTF16-LE with or without a BOM; support UTF-8 with a BOM; support +# UTF-32BE and UTF-32LE with or without a BOM; fixed crashing bug if no +# XML parsers are available; added support for 'Content-encoding: deflate'; +# send blank 'Accept-encoding: ' header if neither gzip nor zlib modules +# are available +#3.3 - 7/15/2004 - MAP - optimize EBCDIC to ASCII conversion; fix obscure +# problem tracking xml:base and xml:lang if element declares it, child +# doesn't, first grandchild redeclares it, and second grandchild doesn't; +# refactored date parsing; defined public registerDateHandler so callers +# can add support for additional date formats at runtime; added support +# for OnBlog, Nate, MSSQL, Greek, and Hungarian dates (ytrewq1); added +# zopeCompatibilityHack() which turns FeedParserDict into a regular +# dictionary, required for Zope compatibility, and also makes command- +# line debugging easier because pprint module formats real dictionaries +# better than dictionary-like objects; added NonXMLContentType exception, +# which is stored in bozo_exception when a feed is served with a non-XML +# media type such as 'text/plain'; respect Content-Language as default +# language if not xml:lang is present; cloud dict is now FeedParserDict; +# generator dict is now FeedParserDict; better tracking of xml:lang, +# including support for xml:lang='' to unset the current language; +# recognize RSS 1.0 feeds even when RSS 1.0 namespace is not the default +# namespace; don't overwrite final status on redirects (scenarios: +# redirecting to a URL that returns 304, redirecting to a URL that +# redirects to another URL with a different type of redirect); add +# support for HTTP 303 redirects +#4.0 - MAP - support for relative URIs in xml:base attribute; fixed +# encoding issue with mxTidy (phopkins); preliminary support for RFC 3229; +# support for Atom 1.0; support for iTunes extensions; new 'tags' for +# categories/keywords/etc. as array of dict +# {'term': term, 'scheme': scheme, 'label': label} to match Atom 1.0 +# terminology; parse RFC 822-style dates with no time; lots of other +# bug fixes +#4.1 - MAP - removed socket timeout; added support for chardet library diff --git a/lektury.sqlite b/lektury.sqlite new file mode 100644 index 000000000..cdca909e5 Binary files /dev/null and b/lektury.sqlite differ diff --git a/locale/pl/LC_MESSAGES/django.mo b/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 000000000..b46a010a0 Binary files /dev/null and b/locale/pl/LC_MESSAGES/django.mo differ diff --git a/locale/pl/LC_MESSAGES/django.po b/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 000000000..d2ef7e17a --- /dev/null +++ b/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,105 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-08-10 08:44-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: catalogue/models.py:14 +msgid "author" +msgstr "autor" + +#: catalogue/models.py:15 +msgid "epoch" +msgstr "epoka" + +#: catalogue/models.py:16 +msgid "kind" +msgstr "rodzaj" + +#: catalogue/models.py:17 +msgid "genre" +msgstr "gatunek" + +#: catalogue/models.py:18 +msgid "theme" +msgstr "motyw" + +#: catalogue/models.py:32 +msgid "name" +msgstr "nazwa" + +#: catalogue/models.py:33 catalogue/models.py:59 +msgid "slug" +msgstr "slug" + +#: catalogue/models.py:34 +msgid "sort key" +msgstr "klucz sortowania" + +#: catalogue/models.py:35 +msgid "category" +msgstr "kategoria" + +#: catalogue/models.py:41 catalogue/models.py:73 +msgid "Has description" +msgstr "Ma opis" + +#: catalogue/models.py:50 newtagging/models.py:458 +msgid "tag" +msgstr "tag" + +#: catalogue/models.py:51 newtagging/admin.py:38 +msgid "tags" +msgstr "tagi" + +#: catalogue/models.py:58 +msgid "title" +msgstr "tytuł" + +#: catalogue/models.py:60 +msgid "description" +msgstr "opis" + +#: catalogue/models.py:61 +msgid "creation date" +msgstr "data utworzenia" + +#: catalogue/models.py:64 +msgid "PDF file" +msgstr "plik PDF" + +#: catalogue/models.py:65 +msgid "ODT file" +msgstr "plik ODT" + +#: catalogue/models.py:66 +msgid "HTML file" +msgstr "plik HTML" + +#: catalogue/models.py:82 +msgid "book" +msgstr "książka" + +#: catalogue/models.py:83 +msgid "books" +msgstr "książki" + +#: newtagging/models.py:459 +msgid "content type" +msgstr "typ zawartości" + +#: newtagging/models.py:460 +msgid "object id" +msgstr "id obiektu" diff --git a/manage.py b/manage.py new file mode 100755 index 000000000..5e78ea979 --- /dev/null +++ b/manage.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings) diff --git a/media/.DS_Store b/media/.DS_Store new file mode 100644 index 000000000..d47e30872 Binary files /dev/null and b/media/.DS_Store differ diff --git a/media/books/.DS_Store b/media/books/.DS_Store new file mode 100644 index 000000000..0a63a4f04 Binary files /dev/null and b/media/books/.DS_Store differ diff --git a/media/books/odt/andersen_brzydkie_kaczatko.odt b/media/books/odt/andersen_brzydkie_kaczatko.odt new file mode 100644 index 000000000..7bced51fe Binary files /dev/null and b/media/books/odt/andersen_brzydkie_kaczatko.odt differ diff --git a/media/books/pdf/andersen_brzydkie_kaczatko.pdf b/media/books/pdf/andersen_brzydkie_kaczatko.pdf new file mode 100644 index 000000000..8478abec6 Binary files /dev/null and b/media/books/pdf/andersen_brzydkie_kaczatko.pdf differ diff --git a/media/css/jquery.autocomplete.css b/media/css/jquery.autocomplete.css new file mode 100644 index 000000000..031589cda --- /dev/null +++ b/media/css/jquery.autocomplete.css @@ -0,0 +1,48 @@ +.ac_results { + padding: 0px; + border: 1px solid black; + background-color: white; + overflow: hidden; + z-index: 99999; +} + +.ac_results ul { + width: 100%; + list-style-position: outside; + list-style: none; + padding: 0; + margin: 0; +} + +.ac_results li { + margin: 0px; + padding: 2px 5px; + cursor: default; + display: block; + /* + if width will be 100% horizontal scrollbar will apear + when scroll mode will be used + */ + /*width: 100%;*/ + font: menu; + font-size: 12px; + /* + it is very important, if line-height not setted or setted + in relative units scroll will be broken in firefox + */ + line-height: 16px; + overflow: hidden; +} + +.ac_loading { + background: white url(/pliki/img/indicator.gif) right center no-repeat; +} + +.ac_odd { + background-color: #eee; +} + +.ac_over { + background-color: #0A246A; + color: white; +} diff --git a/media/css/master.css b/media/css/master.css new file mode 100644 index 000000000..f9ff89535 --- /dev/null +++ b/media/css/master.css @@ -0,0 +1,334 @@ +body { + margin: 2em; + font: 70% Verdana, Arial, Helvetica, sans-serif; + line-height: 1.5em; + background: #FFF url(/pliki/img/bg.png) repeat-x; + color: #000; +} + +img { + border: none; +} + +a { + color: #295158; + text-decoration: none; +} + +a:hover, a:active { + text-decoration: underline; +} + +input { + font: 1em Verdana, Arial, Helvetica, sans-serif; +} + +h1 { + font: normal normal bold 2em Arial, sans-serif; + color: #2F4110; + margin: 0.5em 0 0 0; +} + +h2 { + font-size: 1.2em; + font-weight: bold; + color: #2F4110; + margin: 0; +} + +h3 { + font-size: 1.3em; + font-weight: bold; + margin: 0.2em 0 0 0; + color: #333; +} + +.clearboth { + clear: both; +} + +.blur { + color: #999; +} + +/* ================================== */ +/* = Header with logo and user-info = */ +/* ================================== */ +#header { + position: relative; +} + +#header #logo { + float: left; +} + +#header #user-info { + margin: 0 0 0 auto; + width: 40em; + text-align: right; +} + + +/* ======================== */ +/* = Footer with sponsors = */ +/* ======================== */ +#footer { + border-top: 0.1em solid #999; + color: #999; + font-size: 0.8em; + padding-top: 0.5em; + margin: 2em 0 0 0; +} + +#footer p { + margin: 0; +} + +#footer a { + color: #999; + text-decoration: underline; +} + + +/* =============== */ +/* = Search form = */ +/* =============== */ +#search-form { + margin: 0.5em 0; + padding: 0.5em; + background-color: rgb(132, 191, 42); + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + border-bottom: 0.15em solid #7B9C2D; + border-right: 0.15em solid #7B9C2D; +} + +#search-form p { + margin: 0em 0 0 0; +} + +#search-form ol { + margin: 0; + padding: 0; +} + +#search-form li { + margin: 0; + padding: 0; + list-style: none; + display: inline; +} + +#search-form li.category, #search-form li.book-title { + padding: 0.2em 0.5em 0.2em 0.5em; + background-color: rgb(242, 163, 15); + border: 1px solid #BA8722; + border-right: 1px solid #555; + border-bottom: 1px solid #555; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; +} + +#search-form li.book-title { + background-color: #DDD; + border: 1px solid #999; + border-right: 1px solid #555; + border-bottom: 1px solid #555; +} + +#search-form input[type=submit] { + color: #444; +} + +/* TODO: Shouldn't be needed */ +#book-detail #search-form { + padding: 0.75em 0.5em; +} + +.ac_input { + width: 20em; +} + + +/* ============= */ +/* = Tags list = */ +/* ============= */ +#tags-list { + margin-top: 1em; + padding: 1em; + background-color: #FBEF90; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + border-bottom: 0.15em solid #E3D888; + border-right: 0.15em solid #E3D888; +} + +#books #tags-list, #book-detail #tags-list { + margin-left: 39em; +} + +#tags-list ol, #tags-list ul { + padding: 0; + margin: 0.3em 0 1.2em 0; +} + +#tags-list li { + list-style: none; + padding: 0; + margin: 0; +} + +#main-page #categories-list { + float: left; + width: 50%; +} + +#main-page #themes-list { + margin-left: 50%; +} + + +.column { + padding-right: 1em; +} + +.last.column { + padding-right: 0; +} + + +#books-list { + width: 38em; + float: left; +} + +/* ===================== */ +/* = Latest blog posts = */ +/* ===================== */ +#latest-blog-posts { + padding: 0.5em; + margin-top: 0.5em; +} + +#latest-blog-posts ol { + padding: 0 0 0 1.5em; + margin: 0.3em 0 0 0; + list-style-type: square; + color: #D13628; +} + +/* =============== */ +/* = Description = */ +/* =============== */ +#description { + margin-top: 0.5em; + text-align: justify; +} + +#toggle-description, #books .pagination { + width: 100%; + height: 1.5em; + background-color: #EEE; + margin-top: 0.5em; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + text-align: center; +} + +#toggle-description p { + margin: 0; + padding: 0; + color: #999; +} + +/* ============== */ +/* = Books list = */ +/* ============== */ +#books-list { + margin: 0; +} + +#books-list ol { + list-style: none; + padding: 0; + margin: 1.5em 0; +} + +.book { + padding: 0.5em; + background-color: #FFF; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.book .change-sets { + float: right; +} + +.book-description { + margin-left: 3.5em; +} + +.book-thumbnail { + background: transparent url(/pliki/img/book.png) no-repeat 0 0; + width: 3em; + height: 3em; + float: left; +} + +/* =============== */ +/* = Simple form = */ +/* =============== */ +.simple-form ol, .simple-form ul { + padding: 0; + margin: 0; + list-style: none; +} + +.simple-form ol li, .simple-form ul li { + margin-top: 0.5em; +} + +/* ================ */ +/* = Modal Window = */ +/* ================ */ +#set-window { + position: absolute; + display: none; + width: 32em; + background-color: transparent; + color: #333; + margin-top: -0.5em; + margin-left: -1em; +} + +#set-window div.header { + background-color: #FFF; + border-right: 0.5em solid #DDD; + width: 4em; + padding: 0.5em 1em 0.5em 1em; +} + +#set-window div.target { + background-color: #FFF; + border-right: 0.5em solid #DDD; + border-bottom: 0.5em solid #DDD; + padding: 1em; +} + +.jqmOverlay { background-color: #000; } + + +/* ======================== */ +/* = Alphabetic book list = */ +/* ======================== */ +#book-a-list ol { + padding: 0; + margin: 0.3em 0 1.2em 0; + list-style: none; +} diff --git a/media/img/.DS_Store b/media/img/.DS_Store new file mode 100644 index 000000000..95c97e049 Binary files /dev/null and b/media/img/.DS_Store differ diff --git a/media/img/bg.png b/media/img/bg.png new file mode 100644 index 000000000..be7d63a7c Binary files /dev/null and b/media/img/bg.png differ diff --git a/media/img/book.png b/media/img/book.png new file mode 100644 index 000000000..f26483979 Binary files /dev/null and b/media/img/book.png differ diff --git a/media/img/favicon.png b/media/img/favicon.png new file mode 100644 index 000000000..6cffce8e5 Binary files /dev/null and b/media/img/favicon.png differ diff --git a/media/img/footer.png b/media/img/footer.png new file mode 100644 index 000000000..78634239c Binary files /dev/null and b/media/img/footer.png differ diff --git a/media/img/indicator.gif b/media/img/indicator.gif new file mode 100644 index 000000000..085ccaeca Binary files /dev/null and b/media/img/indicator.gif differ diff --git a/media/img/logo.png b/media/img/logo.png new file mode 100644 index 000000000..bf92ee069 Binary files /dev/null and b/media/img/logo.png differ diff --git a/media/img/old/.DS_Store b/media/img/old/.DS_Store new file mode 100644 index 000000000..5008ddfcf Binary files /dev/null and b/media/img/old/.DS_Store differ diff --git a/media/img/old/bg.png b/media/img/old/bg.png new file mode 100644 index 000000000..ab2547b75 Binary files /dev/null and b/media/img/old/bg.png differ diff --git a/media/img/old/book.png b/media/img/old/book.png new file mode 100644 index 000000000..9db0ef96c Binary files /dev/null and b/media/img/old/book.png differ diff --git a/media/img/old/favicon.png b/media/img/old/favicon.png new file mode 100644 index 000000000..57b78223e Binary files /dev/null and b/media/img/old/favicon.png differ diff --git a/media/img/old/footer.png b/media/img/old/footer.png new file mode 100644 index 000000000..4c0c61c62 Binary files /dev/null and b/media/img/old/footer.png differ diff --git a/media/img/old/indicator.gif b/media/img/old/indicator.gif new file mode 100644 index 000000000..085ccaeca Binary files /dev/null and b/media/img/old/indicator.gif differ diff --git a/media/img/old/logo.png b/media/img/old/logo.png new file mode 100644 index 000000000..77cdd0668 Binary files /dev/null and b/media/img/old/logo.png differ diff --git a/media/js/.DS_Store b/media/js/.DS_Store new file mode 100644 index 000000000..28a2b082c Binary files /dev/null and b/media/js/.DS_Store differ diff --git a/media/js/jquery.autocolumn.js b/media/js/jquery.autocolumn.js new file mode 100644 index 000000000..ea896b67f --- /dev/null +++ b/media/js/jquery.autocolumn.js @@ -0,0 +1,202 @@ +// version 1.1.0 +// http://welcome.totheinter.net/columnizer-jquery-plugin/ +// created by: Adam Wulf adam.wulf@gmail.com + +(function($){ + $.fn.columnize = function(options) { + + + var defaults = { + width: 400, + columns : false, + buildOnce : false + }; + var options = $.extend(defaults, options); + + return this.each(function() { + var $inBox = $(this); + var maxHeight = $inBox.height(); + var $cache = $('
'); // this is where we'll put the real content + var lastWidth = 0; + var columnizing = false; + $cache.append($inBox.children().clone()); + + columnizeIt(); + + $(window).resize(function() { + if(!options.buildOnce && $.browser.msie){ + if($inBox.data("timeout")){ + clearTimeout($inBox.data("timeout")); + } + $inBox.data("timeout", setTimeout(columnizeIt, 200)); + }else if(!options.buildOnce){ + columnizeIt(); + }else{ + // don't rebuild + } + }); + + /** + * return a node that has a height + * less than or equal to height + * + * @param putInHere, a dom element + * @$pullOutHere, a jQuery element + */ + function columnize($putInHere, $pullOutHere, $parentColumn, height){ + while($parentColumn.height() < height && + $pullOutHere[0].childNodes.length){ + $putInHere.append($pullOutHere[0].childNodes[0]); + } + if($putInHere[0].childNodes.length == 0) return; + + // now we're too tall, undo the last one + var kids = $putInHere[0].childNodes; + var lastKid = kids[kids.length-1]; + $putInHere[0].removeChild(lastKid); + var $item = $(lastKid); + if($item[0].nodeType == 3){ + // it's a text node, split it up + var oText = $item[0].nodeValue; + var counter2 = options.width / 8; + var columnText; + while($parentColumn.height() < height && oText.length){ + if (oText.indexOf(' ', counter2) != '-1') { + columnText = oText.substring(0, oText.indexOf(' ', counter2)); + } else { + columnText = oText; + } + $putInHere.append(document.createTextNode(columnText)); + if(oText.length > counter2){ + oText = oText.substring(oText.indexOf(' ', counter2)); + }else{ + oText = ""; + } + } + if(oText.length){ + $item[0].nodeValue = oText; + }else{ + return; + } + } + + if($pullOutHere.children().length){ + $pullOutHere.prepend($item); + }else{ + $pullOutHere.append($item); + } + } + + function split($putInHere, $pullOutHere, $parentColumn, height){ + if($pullOutHere.children().length){ + $cloneMe = $pullOutHere.children(":first"); + $clone = $cloneMe.clone(); + if($clone.attr("nodeType") == 1){ + $putInHere.append($clone); + if($clone.is("img") && $parentColumn.height() < height + 20){ + $cloneMe.remove(); + }else if(!$cloneMe.hasClass("dontsplit") && $parentColumn.height() < height + 20){ + $cloneMe.remove(); + }else if($clone.is("img") || $cloneMe.hasClass("dontsplit")){ + $clone.remove(); + }else{ + $clone.empty(); + columnize($clone, $cloneMe, $parentColumn, height); + if($cloneMe.children().length){ + split($clone, $cloneMe, $parentColumn, height); + } + } + } + } + } + + + function singleColumnizeIt() { + if ($inBox.data("columnized") && $inBox.children().length == 1) { + return; + } + $inBox.data("columnized", true); + $inBox.data("columnizing", true); + + $inBox.empty(); + $inBox.append($("
")); //" + $col = $inBox.children().eq($inBox.children().length-1); + $col.append($cache.clone()); + + $inBox.data("columnizing", false); + } + + + function columnizeIt() { + if(lastWidth == $inBox.width()) return; + lastWidth = $inBox.width(); + + var numCols = Math.round($inBox.width() / options.width); + if(options.columns) numCols = options.columns; +// if ($inBox.data("columnized") && numCols == $inBox.children().length) { +// return; +// } + if(numCols <= 1){ + return singleColumnizeIt(); + } + if($inBox.data("columnizing")) return; + $inBox.data("columnized", true); + $inBox.data("columnizing", true); + + $inBox.empty(); + $inBox.append($("
")); //" + $col = $inBox.children(":last"); + $col.append($cache.clone()); + maxHeight = $col.height(); + $inBox.empty(); + + var targetHeight = maxHeight / numCols; + var firstTime = true; + var maxLoops = 3; + for(var loopCount=0;loopCount")); //" + } + + // fill all but the last column + for (var i = 0; i < numCols-1; i++) { + var $col = $inBox.children().eq(i); + columnize($col, $destroyable, $col, targetHeight); + split($col, $destroyable, $col, targetHeight); + } + // the last column in the series + $col = $inBox.children().eq($inBox.children().length-1); + while($destroyable.children().length) $col.append($destroyable.children(":first")); + var afterH = $col.height(); + var diff = afterH - targetHeight; + var totalH = 0; + var min = 10000000; + var max = 0; + $inBox.children().each(function($inBox){ return function($item){ + var h = $inBox.children().eq($item).height(); + totalH += h; + if(h > max) max = h; + if(h < min) min = h; + }}($inBox)); + var avgH = totalH / numCols; + if(max - min > 30){ + targetHeight = avgH + 30; + }else if(Math.abs(avgH-targetHeight) > 20){ + targetHeight = avgH; + }else{ + loopCount = maxLoops; + } + $inBox.append($("
")); + } + $inBox.data("columnizing", false); + } + }); + }; +})(jQuery); diff --git a/media/js/jquery.autocomplete.js b/media/js/jquery.autocomplete.js new file mode 100644 index 000000000..5ad9178f8 --- /dev/null +++ b/media/js/jquery.autocomplete.js @@ -0,0 +1,759 @@ +/* + * Autocomplete - jQuery plugin 1.0.2 + * + * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Revision: $Id: jquery.autocomplete.js 5747 2008-06-25 18:30:55Z joern.zaefferer $ + * + */ + +;(function($) { + +$.fn.extend({ + autocomplete: function(urlOrData, options) { + var isUrl = typeof urlOrData == "string"; + options = $.extend({}, $.Autocompleter.defaults, { + url: isUrl ? urlOrData : null, + data: isUrl ? null : urlOrData, + delay: isUrl ? $.Autocompleter.defaults.delay : 10, + max: options && !options.scroll ? 10 : 150 + }, options); + + // if highlight is set to false, replace it with a do-nothing function + options.highlight = options.highlight || function(value) { return value; }; + + // if the formatMatch option is not specified, then use formatItem for backwards compatibility + options.formatMatch = options.formatMatch || options.formatItem; + + return this.each(function() { + new $.Autocompleter(this, options); + }); + }, + result: function(handler) { + return this.bind("result", handler); + }, + search: function(handler) { + return this.trigger("search", [handler]); + }, + flushCache: function() { + return this.trigger("flushCache"); + }, + setOptions: function(options){ + return this.trigger("setOptions", [options]); + }, + unautocomplete: function() { + return this.trigger("unautocomplete"); + } +}); + +$.Autocompleter = function(input, options) { + + var KEY = { + UP: 38, + DOWN: 40, + DEL: 46, + TAB: 9, + RETURN: 13, + ESC: 27, + COMMA: 188, + PAGEUP: 33, + PAGEDOWN: 34, + BACKSPACE: 8 + }; + + // Create $ object for input element + var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass); + + var timeout; + var previousValue = ""; + var cache = $.Autocompleter.Cache(options); + var hasFocus = 0; + var lastKeyPressCode; + var config = { + mouseDownOnSelect: false + }; + var select = $.Autocompleter.Select(options, input, selectCurrent, config); + + var blockSubmit; + + // prevent form submit in opera when selecting with return key + $.browser.opera && $(input.form).bind("submit.autocomplete", function() { + if (blockSubmit) { + blockSubmit = false; + return false; + } + }); + + // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all + $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) { + // track last key pressed + lastKeyPressCode = event.keyCode; + switch(event.keyCode) { + + case KEY.UP: + event.preventDefault(); + if ( select.visible() ) { + select.prev(); + } else { + onChange(0, true); + } + break; + + case KEY.DOWN: + event.preventDefault(); + if ( select.visible() ) { + select.next(); + } else { + onChange(0, true); + } + break; + + case KEY.PAGEUP: + event.preventDefault(); + if ( select.visible() ) { + select.pageUp(); + } else { + onChange(0, true); + } + break; + + case KEY.PAGEDOWN: + event.preventDefault(); + if ( select.visible() ) { + select.pageDown(); + } else { + onChange(0, true); + } + break; + + // matches also semicolon + case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA: + case KEY.TAB: + case KEY.RETURN: + if( selectCurrent() ) { + // stop default to prevent a form submit, Opera needs special handling + event.preventDefault(); + blockSubmit = true; + return false; + } + break; + + case KEY.ESC: + select.hide(); + break; + + default: + clearTimeout(timeout); + timeout = setTimeout(onChange, options.delay); + break; + } + }).focus(function(){ + // track whether the field has focus, we shouldn't process any + // results if the field no longer has focus + hasFocus++; + }).blur(function() { + hasFocus = 0; + if (!config.mouseDownOnSelect) { + hideResults(); + } + }).click(function() { + // show select when clicking in a focused field + if ( hasFocus++ > 1 && !select.visible() ) { + onChange(0, true); + } + }).bind("search", function() { + // TODO why not just specifying both arguments? + var fn = (arguments.length > 1) ? arguments[1] : null; + function findValueCallback(q, data) { + var result; + if( data && data.length ) { + for (var i=0; i < data.length; i++) { + if( data[i].result.toLowerCase() == q.toLowerCase() ) { + result = data[i]; + break; + } + } + } + if( typeof fn == "function" ) fn(result); + else $input.trigger("result", result && [result.data, result.value]); + } + $.each(trimWords($input.val()), function(i, value) { + request(value, findValueCallback, findValueCallback); + }); + }).bind("flushCache", function() { + cache.flush(); + }).bind("setOptions", function() { + $.extend(options, arguments[1]); + // if we've updated the data, repopulate + if ( "data" in arguments[1] ) + cache.populate(); + }).bind("unautocomplete", function() { + select.unbind(); + $input.unbind(); + $(input.form).unbind(".autocomplete"); + }); + + + function selectCurrent() { + var selected = select.selected(); + if( !selected ) + return false; + + var v = selected.result; + previousValue = v; + + if ( options.multiple ) { + var words = trimWords($input.val()); + if ( words.length > 1 ) { + v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v; + } + v += options.multipleSeparator; + } + + $input.val(v); + hideResultsNow(); + $input.trigger("result", [selected.data, selected.value]); + return true; + } + + function onChange(crap, skipPrevCheck) { + if( lastKeyPressCode == KEY.DEL ) { + select.hide(); + return; + } + + var currentValue = $input.val(); + + if ( !skipPrevCheck && currentValue == previousValue ) + return; + + previousValue = currentValue; + + currentValue = lastWord(currentValue); + if ( currentValue.length >= options.minChars) { + $input.addClass(options.loadingClass); + if (!options.matchCase) + currentValue = currentValue.toLowerCase(); + request(currentValue, receiveData, hideResultsNow); + } else { + stopLoading(); + select.hide(); + } + }; + + function trimWords(value) { + if ( !value ) { + return [""]; + } + var words = value.split( options.multipleSeparator ); + var result = []; + $.each(words, function(i, value) { + if ( $.trim(value) ) + result[i] = $.trim(value); + }); + return result; + } + + function lastWord(value) { + if ( !options.multiple ) + return value; + var words = trimWords(value); + return words[words.length - 1]; + } + + // fills in the input box w/the first match (assumed to be the best match) + // q: the term entered + // sValue: the first matching result + function autoFill(q, sValue){ + // autofill in the complete box w/the first match as long as the user hasn't entered in more data + // if the last user key pressed was backspace, don't autofill + if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) { + // fill in the value (keep the case the user has typed) + $input.val($input.val() + sValue.substring(lastWord(previousValue).length)); + // select the portion of the value not typed by the user (so the next character will erase) + $.Autocompleter.Selection(input, previousValue.length, previousValue.length + sValue.length); + } + }; + + function hideResults() { + clearTimeout(timeout); + timeout = setTimeout(hideResultsNow, 200); + }; + + function hideResultsNow() { + var wasVisible = select.visible(); + select.hide(); + clearTimeout(timeout); + stopLoading(); + if (options.mustMatch) { + // call search and run callback + $input.search( + function (result){ + // if no value found, clear the input box + if( !result ) { + if (options.multiple) { + var words = trimWords($input.val()).slice(0, -1); + $input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") ); + } + else + $input.val( "" ); + } + } + ); + } + if (wasVisible) + // position cursor at end of input field + $.Autocompleter.Selection(input, input.value.length, input.value.length); + }; + + function receiveData(q, data) { + if ( data && data.length && hasFocus ) { + stopLoading(); + select.display(data, q); + autoFill(q, data[0].value); + select.show(); + } else { + hideResultsNow(); + } + }; + + function request(term, success, failure) { + if (!options.matchCase) + term = term.toLowerCase(); + var data = cache.load(term); + // recieve the cached data + if (data && data.length) { + success(term, data); + // if an AJAX url has been supplied, try loading the data now + } else if( (typeof options.url == "string") && (options.url.length > 0) ){ + + var extraParams = { + timestamp: +new Date() + }; + $.each(options.extraParams, function(key, param) { + extraParams[key] = typeof param == "function" ? param() : param; + }); + + $.ajax({ + // try to leverage ajaxQueue plugin to abort previous requests + mode: "abort", + // limit abortion to this input + port: "autocomplete" + input.name, + dataType: options.dataType, + url: options.url, + data: $.extend({ + q: lastWord(term), + limit: options.max + }, extraParams), + success: function(data) { + var parsed = options.parse && options.parse(data) || parse(data); + cache.add(term, parsed); + success(term, parsed); + } + }); + } else { + // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match + select.emptyList(); + failure(term); + } + }; + + function parse(data) { + var parsed = []; + var rows = data.split("\n"); + for (var i=0; i < rows.length; i++) { + var row = $.trim(rows[i]); + if (row) { + row = row.split("|"); + parsed[parsed.length] = { + data: row, + value: row[0], + result: options.formatResult && options.formatResult(row, row[0]) || row[0] + }; + } + } + return parsed; + }; + + function stopLoading() { + $input.removeClass(options.loadingClass); + }; + +}; + +$.Autocompleter.defaults = { + inputClass: "ac_input", + resultsClass: "ac_results", + loadingClass: "ac_loading", + minChars: 1, + delay: 400, + matchCase: false, + matchSubset: true, + matchContains: false, + cacheLength: 10, + max: 100, + mustMatch: false, + extraParams: {}, + selectFirst: true, + formatItem: function(row) { return row[0]; }, + formatMatch: null, + autoFill: false, + width: 0, + multiple: false, + multipleSeparator: ", ", + highlight: function(value, term) { + return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "$1"); + }, + scroll: true, + scrollHeight: 180 +}; + +$.Autocompleter.Cache = function(options) { + + var data = {}; + var length = 0; + + function matchSubset(s, sub) { + if (!options.matchCase) + s = s.toLowerCase(); + var i = s.indexOf(sub); + if (i == -1) return false; + return i == 0 || options.matchContains; + }; + + function add(q, value) { + if (length > options.cacheLength){ + flush(); + } + if (!data[q]){ + length++; + } + data[q] = value; + } + + function populate(){ + if( !options.data ) return false; + // track the matches + var stMatchSets = {}, + nullData = 0; + + // no url was specified, we need to adjust the cache length to make sure it fits the local data store + if( !options.url ) options.cacheLength = 1; + + // track all options for minChars = 0 + stMatchSets[""] = []; + + // loop through the array and create a lookup structure + for ( var i = 0, ol = options.data.length; i < ol; i++ ) { + var rawValue = options.data[i]; + // if rawValue is a string, make an array otherwise just reference the array + rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue; + + var value = options.formatMatch(rawValue, i+1, options.data.length); + if ( value === false ) + continue; + + var firstChar = value.charAt(0).toLowerCase(); + // if no lookup array for this character exists, look it up now + if( !stMatchSets[firstChar] ) + stMatchSets[firstChar] = []; + + // if the match is a string + var row = { + value: value, + data: rawValue, + result: options.formatResult && options.formatResult(rawValue) || value + }; + + // push the current match into the set list + stMatchSets[firstChar].push(row); + + // keep track of minChars zero items + if ( nullData++ < options.max ) { + stMatchSets[""].push(row); + } + }; + + // add the data items to the cache + $.each(stMatchSets, function(i, value) { + // increase the cache size + options.cacheLength++; + // add to the cache + add(i, value); + }); + } + + // populate any existing data + setTimeout(populate, 25); + + function flush(){ + data = {}; + length = 0; + } + + return { + flush: flush, + add: add, + populate: populate, + load: function(q) { + if (!options.cacheLength || !length) + return null; + /* + * if dealing w/local data and matchContains than we must make sure + * to loop through all the data collections looking for matches + */ + if( !options.url && options.matchContains ){ + // track all matches + var csub = []; + // loop through all the data grids for matches + for( var k in data ){ + // don't search through the stMatchSets[""] (minChars: 0) cache + // this prevents duplicates + if( k.length > 0 ){ + var c = data[k]; + $.each(c, function(i, x) { + // if we've got a match, add it to the array + if (matchSubset(x.value, q)) { + csub.push(x); + } + }); + } + } + return csub; + } else + // if the exact item exists, use it + if (data[q]){ + return data[q]; + } else + if (options.matchSubset) { + for (var i = q.length - 1; i >= options.minChars; i--) { + var c = data[q.substr(0, i)]; + if (c) { + var csub = []; + $.each(c, function(i, x) { + if (matchSubset(x.value, q)) { + csub[csub.length] = x; + } + }); + return csub; + } + } + } + return null; + } + }; +}; + +$.Autocompleter.Select = function (options, input, select, config) { + var CLASSES = { + ACTIVE: "ac_over" + }; + + var listItems, + active = -1, + data, + term = "", + needsInit = true, + element, + list; + + // Create results + function init() { + if (!needsInit) + return; + element = $("
") + .hide() + .addClass(options.resultsClass) + .css("position", "absolute") + .appendTo(document.body); + + list = $("
    ").appendTo(element).mouseover( function(event) { + if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') { + active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event)); + $(target(event)).addClass(CLASSES.ACTIVE); + } + }).click(function(event) { + $(target(event)).addClass(CLASSES.ACTIVE); + select(); + // TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus + input.focus(); + return false; + }).mousedown(function() { + config.mouseDownOnSelect = true; + }).mouseup(function() { + config.mouseDownOnSelect = false; + }); + + if( options.width > 0 ) + element.css("width", options.width); + + needsInit = false; + } + + function target(event) { + var element = event.target; + while(element && element.tagName != "LI") + element = element.parentNode; + // more fun with IE, sometimes event.target is empty, just ignore it then + if(!element) + return []; + return element; + } + + function moveSelect(step) { + listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE); + movePosition(step); + var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE); + if(options.scroll) { + var offset = 0; + listItems.slice(0, active).each(function() { + offset += this.offsetHeight; + }); + if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) { + list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight()); + } else if(offset < list.scrollTop()) { + list.scrollTop(offset); + } + } + }; + + function movePosition(step) { + active += step; + if (active < 0) { + active = listItems.size() - 1; + } else if (active >= listItems.size()) { + active = 0; + } + } + + function limitNumberOfItems(available) { + return options.max && options.max < available + ? options.max + : available; + } + + function fillList() { + list.empty(); + var max = limitNumberOfItems(data.length); + for (var i=0; i < max; i++) { + if (!data[i]) + continue; + var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term); + if ( formatted === false ) + continue; + var li = $("
  • ").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0]; + $.data(li, "ac_data", data[i]); + } + listItems = list.find("li"); + if ( options.selectFirst ) { + listItems.slice(0, 1).addClass(CLASSES.ACTIVE); + active = 0; + } + // apply bgiframe if available + if ( $.fn.bgiframe ) + list.bgiframe(); + } + + return { + display: function(d, q) { + init(); + data = d; + term = q; + fillList(); + }, + next: function() { + moveSelect(1); + }, + prev: function() { + moveSelect(-1); + }, + pageUp: function() { + if (active != 0 && active - 8 < 0) { + moveSelect( -active ); + } else { + moveSelect(-8); + } + }, + pageDown: function() { + if (active != listItems.size() - 1 && active + 8 > listItems.size()) { + moveSelect( listItems.size() - 1 - active ); + } else { + moveSelect(8); + } + }, + hide: function() { + element && element.hide(); + listItems && listItems.removeClass(CLASSES.ACTIVE); + active = -1; + }, + visible : function() { + return element && element.is(":visible"); + }, + current: function() { + return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]); + }, + show: function() { + var offset = $(input).offset(); + element.css({ + width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(), + top: offset.top + input.offsetHeight, + left: offset.left + }).show(); + if(options.scroll) { + list.scrollTop(0); + list.css({ + maxHeight: options.scrollHeight, + overflow: 'auto' + }); + + if($.browser.msie && typeof document.body.style.maxHeight === "undefined") { + var listHeight = 0; + listItems.each(function() { + listHeight += this.offsetHeight; + }); + var scrollbarsVisible = listHeight > options.scrollHeight; + list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight ); + if (!scrollbarsVisible) { + // IE doesn't recalculate width when scrollbar disappears + listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) ); + } + } + + } + }, + selected: function() { + var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE); + return selected && selected.length && $.data(selected[0], "ac_data"); + }, + emptyList: function (){ + list && list.empty(); + }, + unbind: function() { + element && element.remove(); + } + }; +}; + +$.Autocompleter.Selection = function(field, start, end) { + if( field.createTextRange ){ + var selRange = field.createTextRange(); + selRange.collapse(true); + selRange.moveStart("character", start); + selRange.moveEnd("character", end); + selRange.select(); + } else if( field.setSelectionRange ){ + field.setSelectionRange(start, end); + } else { + if( field.selectionStart ){ + field.selectionStart = start; + field.selectionEnd = end; + } + } + field.focus(); +}; + +})(jQuery); \ No newline at end of file diff --git a/media/js/jquery.form.js b/media/js/jquery.form.js new file mode 100644 index 000000000..659baa989 --- /dev/null +++ b/media/js/jquery.form.js @@ -0,0 +1,601 @@ +/* + * jQuery Form Plugin + * version: 2.12 (06/07/2008) + * @requires jQuery v1.2.2 or later + * + * Examples and documentation at: http://malsup.com/jquery/form/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Revision: $Id$ + */ +(function($) { + +/* + Usage Note: + ----------- + Do not use both ajaxSubmit and ajaxForm on the same form. These + functions are intended to be exclusive. Use ajaxSubmit if you want + to bind your own submit handler to the form. For example, + + $(document).ready(function() { + $('#myForm').bind('submit', function() { + $(this).ajaxSubmit({ + target: '#output' + }); + return false; // <-- important! + }); + }); + + Use ajaxForm when you want the plugin to manage all the event binding + for you. For example, + + $(document).ready(function() { + $('#myForm').ajaxForm({ + target: '#output' + }); + }); + + When using ajaxForm, the ajaxSubmit function will be invoked for you + at the appropriate time. +*/ + +/** + * ajaxSubmit() provides a mechanism for immediately submitting + * an HTML form using AJAX. + */ +$.fn.ajaxSubmit = function(options) { + // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) + if (!this.length) { + log('ajaxSubmit: skipping submit process - no element selected'); + return this; + } + + if (typeof options == 'function') + options = { success: options }; + + options = $.extend({ + url: this.attr('action') || window.location.toString(), + type: this.attr('method') || 'GET' + }, options || {}); + + // hook for manipulating the form data before it is extracted; + // convenient for use with rich editors like tinyMCE or FCKEditor + var veto = {}; + this.trigger('form-pre-serialize', [this, options, veto]); + if (veto.veto) { + log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); + return this; + } + + var a = this.formToArray(options.semantic); + if (options.data) { + options.extraData = options.data; + for (var n in options.data) + a.push( { name: n, value: options.data[n] } ); + } + + // give pre-submit callback an opportunity to abort the submit + if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { + log('ajaxSubmit: submit aborted via beforeSubmit callback'); + return this; + } + + // fire vetoable 'validate' event + this.trigger('form-submit-validate', [a, this, options, veto]); + if (veto.veto) { + log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); + return this; + } + + var q = $.param(a); + + if (options.type.toUpperCase() == 'GET') { + options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; + options.data = null; // data is null for 'get' + } + else + options.data = q; // data is the query string for 'post' + + var $form = this, callbacks = []; + if (options.resetForm) callbacks.push(function() { $form.resetForm(); }); + if (options.clearForm) callbacks.push(function() { $form.clearForm(); }); + + // perform a load on the target only if dataType is not provided + if (!options.dataType && options.target) { + var oldSuccess = options.success || function(){}; + callbacks.push(function(data) { + $(options.target).html(data).each(oldSuccess, arguments); + }); + } + else if (options.success) + callbacks.push(options.success); + + options.success = function(data, status) { + for (var i=0, max=callbacks.length; i < max; i++) + callbacks[i](data, status, $form); + }; + + // are there files to upload? + var files = $('input:file', this).fieldValue(); + var found = false; + for (var j=0; j < files.length; j++) + if (files[j]) + found = true; + + // options.iframe allows user to force iframe mode + if (options.iframe || found) { + // hack to fix Safari hang (thanks to Tim Molendijk for this) + // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d + if ($.browser.safari && options.closeKeepAlive) + $.get(options.closeKeepAlive, fileUpload); + else + fileUpload(); + } + else + $.ajax(options); + + // fire 'notify' event + this.trigger('form-submit-notify', [this, options]); + return this; + + + // private function for handling file uploads (hat tip to YAHOO!) + function fileUpload() { + var form = $form[0]; + + if ($(':input[@name=submit]', form).length) { + alert('Error: Form elements must not be named "submit".'); + return; + } + + var opts = $.extend({}, $.ajaxSettings, options); + + var id = 'jqFormIO' + (new Date().getTime()); + var $io = $('').css({opacity:0}), + +// O: The jqModal default Open Callback; +// IF ie6; Add the iframe to the overlay (if overlay exists) OR to the modal (if an iframe doesn't already exist from a previous opening) +// Execute the Modal Focus Function +O=function(h){if(ie6)h.o&&h.o.html('

    ').prepend(i)||(!$('iframe.jqm',h.w)[0]&&h.w.prepend(i)); f(h);}, + +// f: The Modal Focus Function; +// Attempt to focus the first visible input within the modal +f=function(h){try{$(':input:visible',h.w)[0].focus();}catch(e){}}, + +// F: The Keep Focus Function; +// Binds or Unbinds (t) the Focus Examination Function to keypresses and clicks +F=function(t){$()[t]("keypress",x)[t]("keydown",x)[t]("mousedown",x);}, + +// x: The Focus Examination Function; +// Fetch the current modal's Hash as h (supports nested modals) +// Determine if the click/press falls within the modal. If not (r===true); +// call the Modal Focus Function and prevent click/press follow-through (return false [!true]) +// ELSE if so (r===false); follow event (return true [!false]) +x=function(e){var h=H[A[A.length-1]],r=(!$(e.target).parents('.jqmID'+h.s)[0]);r&&f(h);return !r;}, + +// hide-show function; assigns click events to trigger elements that +// hide, show, or hide AND show modals. + +// Expandos (jqmShow and/or jqmHide) are added to all trigger elements. +// These Expandos hold an array of modal serials {INT} to show or hide. + +// w: {DOM Element} The modal element (window/dialog/notice/etc. container) +// e: {DOM Elemet||jQ Selector String} The triggering element +// y: {String} Type (jqmHide||jqmShow) + +// s: {array} the serial number of passed modals, calculated below; +HS=function(w,e,y){var s=[];w.each(function(){s.push(this._jqm)}); + +// for each triggering element attach the jqmHide or jqmShow expando (y) +// or else expand the expando with the current serial array + $(e).each(function(){if(this[y])$.extend(this[y],s); + + // Assign a click event on the trigger element which examines the element's + // jqmHide/Show expandos and attempts to execute $.jqmHide/Show on matching modals + else{this[y]=s;$(this).click(function(){for(var i in {jqmShow:1,jqmHide:1})for(var s in this[i])if(H[this[i][s]])H[this[i][s]].w[i](this);return false;});}});return w;}; +})(jQuery); \ No newline at end of file diff --git a/media/js/jquery.js b/media/js/jquery.js new file mode 100644 index 000000000..82b98e1d7 --- /dev/null +++ b/media/js/jquery.js @@ -0,0 +1,32 @@ +/* + * jQuery 1.2.6 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $ + * $Rev: 5685 $ + */ +(function(){var _jQuery=window.jQuery,_$=window.$;var jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);};var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,isSimple=/^.[^:#\[\.]*$/,undefined;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3])return jQuery().find(selector);return jQuery(elem);}selector=[];}}else +return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(jQuery.makeArray(selector));},jquery:"1.2.6",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value===undefined)return this[0]&&jQuery[type||"attr"](this[0],name);else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else +return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else +selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return this.pushStack(jQuery.unique(jQuery.merge(this.get(),typeof selector=='string'?jQuery(selector):jQuery.makeArray(selector))));},is:function(selector){return!!selector&&jQuery.multiFilter(selector,this).length>0;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=jQuery.makeArray(value);jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else +this.value=value;});},html:function(value){return value==undefined?(this[0]?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)data=jQuery.data(this[0],key);return data===undefined&&parts[1]?this.data(parts[0]):data;}else +return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script"))scripts=scripts.add(elem);else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.fn.init.prototype=jQuery.fn;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else +jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}function now(){return+new Date;}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==i){target=this;--i;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else +jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret,style=elem.style;function color(elem){if(!jQuery.browser.safari)return false;var ret=defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=style.outline;style.outline="0 solid black";style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&style&&style[name])ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle&&!color(elem))ret=computedStyle.getPropertyValue(name);else{var swap=[],stack=[],a=elem,i=0;for(;a&&color(a);a=a.parentNode)stack.unshift(a);for(;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
    "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div

    ","
    "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else +ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var notxml=!jQuery.isXMLDoc(elem),set=value!==undefined,msie=jQuery.browser.msie;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(name in elem&¬xml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem[name]=value;}if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))return elem.getAttributeNode(name).nodeValue;return elem[name];}if(msie&¬xml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&¬xml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}if(msie&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||array.split||array.setInterval||array.call)ret[0]=array;else +while(i)ret[--i]=array[i];}return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false,re=quickChild,m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[],cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&n!=elem)r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=this.proxy(fn,function(){return fn.apply(this,arguments);});handler.data=data;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){if(typeof jQuery!="undefined"&&!jQuery.event.triggered)return jQuery.event.handle.apply(arguments.callee.elem,arguments);});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else +for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift({type:type,target:elem,preventDefault:function(){},stopPropagation:function(){},timeStamp:now()});data[0][expando]=true;}data[0].type=type;if(exclusive)data[0].exclusive=true;var handle=jQuery.data(elem,"handle");if(handle)val=handle.apply(elem,data);if((!fn||(jQuery.nodeName(elem,'a')&&type=="click"))&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val,ret,namespace,all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);namespace=event.type.split(".");event.type=namespace[0];namespace=namespace[1];all=!namespace&&!event.exclusive;handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||handler.type==namespace){event.handler=handler;event.data=handler.data;ret=handler.apply(this,arguments);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}return val;},fix:function(event){if(event[expando]==true)return event;var originalEvent=event;event={originalEvent:originalEvent};var props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");for(var i=props.length;i;i--)event[props[i]]=originalEvent[props[i]];event[expando]=true;event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};event.timeStamp=event.timeStamp||now();if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=event.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},proxy:function(fn,proxy){proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){return this[0]&&jQuery.event.trigger(type,data,this[0],false,fn);},toggle:function(fn){var args=arguments,i=1;while(i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
    ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=now();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{url:location.href,global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="GET"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");var remote=/^(?:\w+:)?\/\/([^\/?#]+)/;if(s.dataType=="script"&&type=="GET"&&remote.test(s.url)&&remote.exec(s.url)[1]!=location.host){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xhr=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();if(s.username)xhr.open(type,s.url,s.async,s.username,s.password);else +xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else +jQuery.handleError(s,xhr,status);complete();if(s.async)xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xhr){xhr.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xhr,s]);}function complete(){if(s.complete)s.complete(xhr,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url]||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpData:function(xhr,type,filter){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(filter)data=filter(data,type);if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else +for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else +s.push(encodeURIComponent(j)+"="+encodeURIComponent(jQuery.isFunction(a[j])?a[j]():a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle.apply(this,arguments):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall),p,hidden=jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return opt.complete.call(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else +e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.call(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(elem){type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",jQuery.makeArray(array));}return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].call(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:jQuery.fx.speeds[opt.duration])||jQuery.fx.speeds.def;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.call(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.call(this.elem,this.now,this);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=now();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done)this.options.complete.call(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.extend(jQuery.fx,{speeds:{slow:600,fast:200,def:400},step:{scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}}});jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),css=jQuery.curCSS,fixed=css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||css(offsetChild,"position")=="absolute"))||(mozilla&&css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l,10)||0;top+=parseInt(t,10)||0;}return results;};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom";jQuery.fn["inner"+name]=function(){return this[name.toLowerCase()]()+num(this,"padding"+tl)+num(this,"padding"+br);};jQuery.fn["outer"+name]=function(margin){return this["inner"+name]()+num(this,"border"+tl+"Width")+num(this,"border"+br+"Width")+(margin?num(this,"margin"+tl)+num(this,"margin"+br):0);};});})(); \ No newline at end of file diff --git a/media/js/jquery.labelify.js b/media/js/jquery.labelify.js new file mode 100644 index 000000000..13196b289 --- /dev/null +++ b/media/js/jquery.labelify.js @@ -0,0 +1,89 @@ +/** + * jQuery.labelify - Display in-textbox hints + * Stuart Langridge, http://www.kryogenix.org/ + * Released into the public domain + * Date: 25th June 2008 + * @author Stuart Langridge + * @version 1.3 + * + * + * Basic calling syntax: $("input").labelify(); + * Defaults to taking the in-field label from the field's title attribute + * + * You can also pass an options object with the following keys: + * text + * "title" to get the in-field label from the field's title attribute + * (this is the default) + * "label" to get the in-field label from the inner text of the field's label + * (note that the label must be attached to the field with for="fieldid") + * a function which takes one parameter, the input field, and returns + * whatever text it likes + * + * labelledClass + * a class that will be applied to the input field when it contains the + * label and removed when it contains user input. Defaults to blank. + * + */ +jQuery.fn.labelify = function(settings) { + settings = jQuery.extend({ + text: "title", + labelledClass: "" + }, settings); + var lookups = { + title: function(input) { + return $(input).attr("title"); + }, + label: function(input) { + return $("label[for=" + input.id +"]").text(); + } + }; + var lookup; + var jQuery_labellified_elements = $(this); + return $(this).each(function() { + if (typeof settings.text === "string") { + lookup = lookups[settings.text]; // what if not there? + } else { + lookup = settings.text; // what if not a fn? + }; + // bail if lookup isn't a function or if it returns undefined + if (typeof lookup !== "function") { return; } + var lookupval = lookup(this); + if (!lookupval) { return; } + + // need to strip newlines because the browser strips them + // if you set textbox.value to a string containing them + $(this).data("label",lookup(this).replace(/\n/g,'')); + $(this).focus(function() { + if (this.value === $(this).data("label")) { + this.value = this.defaultValue; + $(this).removeClass(settings.labelledClass); + } + }).blur(function(){ + if (this.value === this.defaultValue) { + this.value = $(this).data("label"); + $(this).addClass(settings.labelledClass); + } + }); + + var removeValuesOnExit = function() { + jQuery_labellified_elements.each(function(){ + if (this.value === $(this).data("label")) { + this.value = this.defaultValue; + $(this).removeClass(settings.labelledClass); + } + }) + }; + + $(this).parents("form").submit(removeValuesOnExit); + $(window).unload(removeValuesOnExit); + + if (this.value !== this.defaultValue) { + // user already started typing; don't overwrite their work! + return; + } + // actually set the value + this.value = $(this).data("label"); + $(this).addClass(settings.labelledClass); + + }); +}; \ No newline at end of file diff --git a/middleware.py b/middleware.py new file mode 100644 index 000000000..c9a17dc3a --- /dev/null +++ b/middleware.py @@ -0,0 +1,126 @@ +# Orignal version taken from http://www.djangosnippets.org/snippets/186/ +# Original author: udfalkso +# Modified by: Shwagroo Team + +import sys +import os +import re +import hotshot, hotshot.stats +import tempfile +import StringIO +import pprint + +from django.conf import settings +from django.db import connection + + +words_re = re.compile( r'\s+' ) + +group_prefix_re = [ + re.compile( "^.*/django/[^/]+" ), + re.compile( "^(.*)/[^/]+$" ), # extract module path + re.compile( ".*" ), # catch strange entries +] + + +class ProfileMiddleware(object): + """ + Displays hotshot profiling for any view. + http://yoursite.com/yourview/?prof + + Add the "prof" key to query string by appending ?prof (or &prof=) + and you'll see the profiling results in your browser. + It's set up to only be available in django's debug mode, is available for superuser otherwise, + but you really shouldn't add this middleware to any production configuration. + + WARNING: It uses hotshot profiler which is not thread safe. + """ + def process_request(self, request): + if (settings.DEBUG or request.user.is_superuser) and request.GET.has_key('prof'): + connection.queries = [] + self.tmpfile = tempfile.mktemp() + self.prof = hotshot.Profile(self.tmpfile) + + def process_view(self, request, callback, callback_args, callback_kwargs): + if (settings.DEBUG or request.user.is_superuser) and request.GET.has_key('prof'): + return self.prof.runcall(callback, request, *callback_args, **callback_kwargs) + + def get_group(self, file): + for g in group_prefix_re: + name = g.findall( file ) + if name: + return name[0] + + def get_summary(self, results_dict, sum): + list = [ (item[1], item[0]) for item in results_dict.items() ] + list.sort( reverse = True ) + list = list[:40] + + res = " tottime\n" + for item in list: + if sum == 0: + foo = 0 + else: + foo = 100*item[0]/sum + res += "%4.1f%% %7.3f %s\n" % (foo, item[0], item[1] ) + + return res + + def summary_for_files(self, stats_str): + stats_str = stats_str.split("\n")[5:] + + mystats = {} + mygroups = {} + + sum = 0 + + for s in stats_str: + fields = words_re.split(s); + if len(fields) == 7: + time = float(fields[2]) + sum += time + file = fields[6].split(":")[0] + + if not file in mystats: + mystats[file] = 0 + mystats[file] += time + + group = self.get_group(file) + if not group in mygroups: + mygroups[ group ] = 0 + mygroups[ group ] += time + + return "
    " + \
    +               " ---- By file ----\n\n" + self.get_summary(mystats,sum) + "\n" + \
    +               " ---- By group ---\n\n" + self.get_summary(mygroups,sum) + \
    +               "
    " + + def process_response(self, request, response): + if (settings.DEBUG or request.user.is_superuser) and request.GET.has_key('prof'): + self.prof.close() + + out = StringIO.StringIO() + old_stdout = sys.stdout + sys.stdout = out + + stats = hotshot.stats.load(self.tmpfile) + stats.sort_stats('time', 'calls') + stats.print_stats() + + sys.stdout = old_stdout + stats_str = out.getvalue() + + if response and response.content and stats_str: + response.content = "
    " + stats_str + "
    " + + response.content = "\n".join(response.content.split("\n")[:40]) + + response.content += self.summary_for_files(stats_str) + + os.unlink(self.tmpfile) + + response.content += '\n%d SQL Queries:\n' % len(connection.queries) + response.content += pprint.pformat(connection.queries) + + return response + diff --git a/newtagging/__init__.py b/newtagging/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/newtagging/admin.py b/newtagging/admin.py new file mode 100644 index 000000000..2ecc84d87 --- /dev/null +++ b/newtagging/admin.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +from django.contrib import admin +from django import forms +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext_lazy as _ + + +class FilteredSelectMultiple(forms.SelectMultiple): + """ + A SelectMultiple with a JavaScript filter interface. + + Note that the resulting JavaScript assumes that the SelectFilter2.js + library and its dependencies have been loaded in the HTML page. + """ + def _media(self): + from django.conf import settings + js = ['js/SelectBox.js' , 'js/SelectFilter2.js'] + return forms.Media(js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js]) + media = property(_media) + + def __init__(self, verbose_name, is_stacked, attrs=None, choices=()): + self.verbose_name = verbose_name + self.is_stacked = is_stacked + super(FilteredSelectMultiple, self).__init__(attrs, choices) + + def render(self, name, value, attrs=None, choices=()): + from django.conf import settings + output = [super(FilteredSelectMultiple, self).render(name, value, attrs, choices)] + output.append(u'\n' % \ + (name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.ADMIN_MEDIA_PREFIX)) + return mark_safe(u''.join(output)) + + +class TaggableModelForm(forms.ModelForm): + tags = forms.MultipleChoiceField(label=_('tags').capitalize(), required=True, widget=FilteredSelectMultiple(_('tags'), False)) + + def __init__(self, *args, **kwargs): + self.tags.choices = [(tag.id, tag.name) for tag in self.tag_model.objects.all()] + if 'instance' in kwargs: + if 'initial' not in kwargs: + kwargs['initial'] = {} + kwargs['initial']['tags'] = [tag.id for tag in self.tag_model.objects.get_for_object(kwargs['instance'])] + super(TaggableModelForm, self).__init__(*args, **kwargs) + + def save(self, commit): + obj = super(TaggableModelForm, self).save() + tag_ids = self.cleaned_data['tags'] + tags = self.tag_model.objects.filter(pk__in=tag_ids) + self.tag_model.objects.update_tags(obj, tags) + return obj + + def save_m2m(self): + # TODO: Shouldn't be needed + pass + + +class TaggableModelAdmin(admin.ModelAdmin): + form = TaggableModelForm + + def get_form(self, request, obj=None): + form = super(TaggableModelAdmin, self).get_form(request, obj) + form.tag_model = self.tag_model + return form + diff --git a/newtagging/managers.py b/newtagging/managers.py new file mode 100644 index 000000000..04db00fdd --- /dev/null +++ b/newtagging/managers.py @@ -0,0 +1,78 @@ +""" +Custom managers for Django models registered with the tagging +application. +""" +from django.contrib.contenttypes.models import ContentType +from django.db import models + + +class ModelTagManager(models.Manager): + """ + A manager for retrieving tags for a particular model. + """ + def __init__(self, tag_model): + super(ModelTagManager, self).__init__() + self.tag_model = tag_model + + def get_query_set(self): + content_type = ContentType.objects.get_for_model(self.model) + return self.tag_model.objects.filter( + items__content_type__pk=content_type.pk).distinct() + + def related(self, tags, *args, **kwargs): + return self.tag_model.objects.related_for_model(tags, self.model, *args, **kwargs) + + def usage(self, *args, **kwargs): + return self.tag_model.objects.usage_for_model(self.model, *arg, **kwargs) + + +class ModelTaggedItemManager(models.Manager): + """ + A manager for retrieving model instances based on their tags. + """ + def __init__(self, tag_model): + super(ModelTaggedItemManager, self).__init__() + self.intermediary_table_model = tag_model.objects.intermediary_table_model + + def related_to(self, obj, queryset=None, num=None): + if queryset is None: + return self.intermediary_table_model.objects.get_related(obj, self.model, num=num) + else: + return self.intermediary_table_model.objects.get_related(obj, queryset, num=num) + + def with_all(self, tags, queryset=None): + if queryset is None: + return self.intermediary_table_model.objects.get_by_model(self.model, tags) + else: + return self.intermediary_table_model.objects.get_by_model(queryset, tags) + + def with_any(self, tags, queryset=None): + if queryset is None: + return self.intermediary_table_model.objects.get_union_by_model(self.model, tags) + else: + return self.intermediary_table_model.objects.get_union_by_model(queryset, tags) + + +class TagDescriptor(object): + """ + A descriptor which provides access to a ``ModelTagManager`` for + model classes and simple retrieval, updating and deletion of tags + for model instances. + """ + def __init__(self, tag_model): + self.tag_model = tag_model + + def __get__(self, instance, owner): + if not instance: + tag_manager = ModelTagManager(self.tag_model) + tag_manager.model = owner + return tag_manager + else: + return self.tag_model.objects.get_for_object(instance) + + def __set__(self, instance, value): + self.tag_model.objects.update_tags(instance, value) + + def __del__(self, instance): + self.tag_model.objects.update_tags(instance, []) + diff --git a/newtagging/models.py b/newtagging/models.py new file mode 100644 index 000000000..96647726e --- /dev/null +++ b/newtagging/models.py @@ -0,0 +1,501 @@ +""" +Models and managers for generic tagging. +""" +# Python 2.3 compatibility +if not hasattr(__builtins__, 'set'): + from sets import Set as set + +from django.contrib.contenttypes import generic +from django.contrib.contenttypes.models import ContentType +from django.db import connection, models +from django.db.models.query import QuerySet +from django.utils.translation import ugettext_lazy as _ +from django.db.models.base import ModelBase + +from newtagging.utils import get_tag_list, get_queryset_and_model + +qn = connection.ops.quote_name + +try: + from django.db.models.query import parse_lookup +except ImportError: + parse_lookup = None + + +############ +# Managers # +############ + +class TagManager(models.Manager): + def __init__(self, intermediary_table_model): + super(TagManager, self).__init__() + self.intermediary_table_model = intermediary_table_model + + def update_tags(self, obj, tags): + """ + Update tags associated with an object. + """ + content_type = ContentType.objects.get_for_model(obj) + current_tags = list(self.filter(items__content_type__pk=content_type.pk, + items__object_id=obj.pk)) + updated_tags = get_tag_list(tags) + + # Remove tags which no longer apply + tags_for_removal = [tag for tag in current_tags \ + if tag not in updated_tags] + if len(tags_for_removal): + self.intermediary_table_model._default_manager.filter(content_type__pk=content_type.pk, + object_id=obj.pk, + tag__in=tags_for_removal).delete() + # Add new tags + for tag in updated_tags: + if tag not in current_tags: + self.intermediary_table_model._default_manager.create(tag=tag, content_object=obj) + + # def add_tag(self, obj, tag_name): + # """ + # Associates the given object with a tag. + # """ + # tag_names = parse_tag_input(tag_name) + # if not len(tag_names): + # raise AttributeError(_('No tags were given: "%s".') % tag_name) + # if len(tag_names) > 1: + # raise AttributeError(_('Multiple tags were given: "%s".') % tag_name) + # tag_name = tag_names[0] + # # if settings.FORCE_LOWERCASE_TAGS: + # # tag_name = tag_name.lower() + # tag, created = self.get_or_create(name=tag_name) + # ctype = ContentType.objects.get_for_model(obj) + # self.intermediary_table_model._default_manager.get_or_create( + # tag=tag, content_type=ctype, object_id=obj.pk) + + def get_for_object(self, obj): + """ + Create a queryset matching all tags associated with the given + object. + """ + ctype = ContentType.objects.get_for_model(obj) + return self.filter(items__content_type__pk=ctype.pk, + items__object_id=obj.pk) + + def _get_usage(self, model, counts=False, min_count=None, extra_joins=None, extra_criteria=None, params=None, extra=None): + """ + Perform the custom SQL query for ``usage_for_model`` and + ``usage_for_queryset``. + """ + if min_count is not None: counts = True + + model_table = qn(model._meta.db_table) + model_pk = '%s.%s' % (model_table, qn(model._meta.pk.column)) + tag_columns = self._get_tag_columns() + + if extra is None: extra = {} + extra_where = '' + if 'where' in extra: + extra_where = 'AND ' + ' AND '.join(extra['where']) + + query = """ + SELECT DISTINCT %(tag_columns)s%(count_sql)s + FROM + %(tag)s + INNER JOIN %(tagged_item)s + ON %(tag)s.id = %(tagged_item)s.tag_id + INNER JOIN %(model)s + ON %(tagged_item)s.object_id = %(model_pk)s + %%s + WHERE %(tagged_item)s.content_type_id = %(content_type_id)s + %%s + %(extra_where)s + GROUP BY %(tag)s.id, %(tag)s.name + %%s + ORDER BY %(tag)s.%(ordering)s ASC""" % { + 'tag': qn(self.model._meta.db_table), + 'ordering': ', '.join(qn(field) for field in self.model._meta.ordering), + 'tag_columns': tag_columns, + 'count_sql': counts and (', COUNT(%s)' % model_pk) or '', + 'tagged_item': qn(self.intermediary_table_model._meta.db_table), + 'model': model_table, + 'model_pk': model_pk, + 'extra_where': extra_where, + 'content_type_id': ContentType.objects.get_for_model(model).pk, + } + + min_count_sql = '' + if min_count is not None: + min_count_sql = 'HAVING COUNT(%s) >= %%s' % model_pk + params.append(min_count) + + cursor = connection.cursor() + cursor.execute(query % (extra_joins, extra_criteria, min_count_sql), params) + tags = [] + for row in cursor.fetchall(): + t = self.model(*row[:len(self.model._meta.fields)]) + if counts: + t.count = row[len(self.model._meta.fields)] + tags.append(t) + return tags + + def usage_for_model(self, model, counts=False, min_count=None, filters=None, extra=None): + """ + Obtain a list of tags associated with instances of the given + Model class. + + If ``counts`` is True, a ``count`` attribute will be added to + each tag, indicating how many times it has been used against + the Model class in question. + + If ``min_count`` is given, only tags which have a ``count`` + greater than or equal to ``min_count`` will be returned. + Passing a value for ``min_count`` implies ``counts=True``. + + To limit the tags (and counts, if specified) returned to those + used by a subset of the Model's instances, pass a dictionary + of field lookups to be applied to the given Model as the + ``filters`` argument. + """ + if extra is None: extra = {} + if filters is None: filters = {} + + if not parse_lookup: + # post-queryset-refactor (hand off to usage_for_queryset) + queryset = model._default_manager.filter() + for f in filters.items(): + queryset.query.add_filter(f) + usage = self.usage_for_queryset(queryset, counts, min_count, extra) + else: + # pre-queryset-refactor + extra_joins = '' + extra_criteria = '' + params = [] + if len(filters) > 0: + joins, where, params = parse_lookup(filters.items(), model._meta) + extra_joins = ' '.join(['%s %s AS %s ON %s' % (join_type, table, alias, condition) + for (alias, (table, join_type, condition)) in joins.items()]) + extra_criteria = 'AND %s' % (' AND '.join(where)) + usage = self._get_usage(model, counts, min_count, extra_joins, extra_criteria, params, extra) + + return usage + + def usage_for_queryset(self, queryset, counts=False, min_count=None, extra=None): + """ + Obtain a list of tags associated with instances of a model + contained in the given queryset. + + If ``counts`` is True, a ``count`` attribute will be added to + each tag, indicating how many times it has been used against + the Model class in question. + + If ``min_count`` is given, only tags which have a ``count`` + greater than or equal to ``min_count`` will be returned. + Passing a value for ``min_count`` implies ``counts=True``. + """ + if parse_lookup: + raise AttributeError("'TagManager.usage_for_queryset' is not compatible with pre-queryset-refactor versions of Django.") + + extra_joins = ' '.join(queryset.query.get_from_clause()[0][1:]) + where, params = queryset.query.where.as_sql() + if where: + extra_criteria = 'AND %s' % where + else: + extra_criteria = '' + return self._get_usage(queryset.model, counts, min_count, extra_joins, extra_criteria, params, extra) + + def related_for_model(self, tags, model, counts=False, min_count=None, extra=None): + """ + Obtain a list of tags related to a given list of tags - that + is, other tags used by items which have all the given tags. + + If ``counts`` is True, a ``count`` attribute will be added to + each tag, indicating the number of items which have it in + addition to the given list of tags. + + If ``min_count`` is given, only tags which have a ``count`` + greater than or equal to ``min_count`` will be returned. + Passing a value for ``min_count`` implies ``counts=True``. + """ + if min_count is not None: counts = True + tags = get_tag_list(tags) + tag_count = len(tags) + tagged_item_table = qn(self.intermediary_table_model._meta.db_table) + tag_columns = self._get_tag_columns() + + if extra is None: extra = {} + extra_where = '' + if 'where' in extra: + extra_where = 'AND ' + ' AND '.join(extra['where']) + + query = """ + SELECT %(tag_columns)s%(count_sql)s + FROM %(tagged_item)s INNER JOIN %(tag)s ON %(tagged_item)s.tag_id = %(tag)s.id + WHERE %(tagged_item)s.content_type_id = %(content_type_id)s + AND %(tagged_item)s.object_id IN + ( + SELECT %(tagged_item)s.object_id + FROM %(tagged_item)s, %(tag)s + WHERE %(tagged_item)s.content_type_id = %(content_type_id)s + AND %(tag)s.id = %(tagged_item)s.tag_id + AND %(tag)s.id IN (%(tag_id_placeholders)s) + GROUP BY %(tagged_item)s.object_id + HAVING COUNT(%(tagged_item)s.object_id) = %(tag_count)s + ) + AND %(tag)s.id NOT IN (%(tag_id_placeholders)s) + %(extra_where)s + GROUP BY %(tag)s.id, %(tag)s.name + %(min_count_sql)s + ORDER BY %(tag)s.%(ordering)s ASC""" % { + 'tag': qn(self.model._meta.db_table), + 'ordering': ', '.join(qn(field) for field in self.model._meta.ordering), + 'tag_columns': tag_columns, + 'count_sql': counts and ', COUNT(%s.object_id)' % tagged_item_table or '', + 'tagged_item': tagged_item_table, + 'content_type_id': ContentType.objects.get_for_model(model).pk, + 'tag_id_placeholders': ','.join(['%s'] * tag_count), + 'extra_where': extra_where, + 'tag_count': tag_count, + 'min_count_sql': min_count is not None and ('HAVING COUNT(%s.object_id) >= %%s' % tagged_item_table) or '', + } + + params = [tag.pk for tag in tags] * 2 + if min_count is not None: + params.append(min_count) + + cursor = connection.cursor() + cursor.execute(query, params) + related = [] + for row in cursor.fetchall(): + tag = self.model(*row[:len(self.model._meta.fields)]) + if counts is True: + tag.count = row[len(self.model._meta.fields)] + related.append(tag) + return related + + def _get_tag_columns(self): + tag_table = qn(self.model._meta.db_table) + return ', '.join('%s.%s' % (tag_table, qn(field.column)) for field in self.model._meta.fields) + + +class TaggedItemManager(models.Manager): + """ + FIXME There's currently no way to get the ``GROUP BY`` and ``HAVING`` + SQL clauses required by many of this manager's methods into + Django's ORM. + + For now, we manually execute a query to retrieve the PKs of + objects we're interested in, then use the ORM's ``__in`` + lookup to return a ``QuerySet``. + + Once the queryset-refactor branch lands in trunk, this can be + tidied up significantly. + """ + def get_by_model(self, queryset_or_model, tags): + """ + Create a ``QuerySet`` containing instances of the specified + model associated with a given tag or list of tags. + """ + tags = get_tag_list(tags) + tag_count = len(tags) + if tag_count == 0: + # No existing tags were given + queryset, model = get_queryset_and_model(queryset_or_model) + return model._default_manager.none() + elif tag_count == 1: + # Optimisation for single tag - fall through to the simpler + # query below. + tag = tags[0] + else: + return self.get_intersection_by_model(queryset_or_model, tags) + + queryset, model = get_queryset_and_model(queryset_or_model) + content_type = ContentType.objects.get_for_model(model) + opts = self.model._meta + tagged_item_table = qn(opts.db_table) + return queryset.extra( + tables=[opts.db_table], + where=[ + '%s.content_type_id = %%s' % tagged_item_table, + '%s.tag_id = %%s' % tagged_item_table, + '%s.%s = %s.object_id' % (qn(model._meta.db_table), + qn(model._meta.pk.column), + tagged_item_table) + ], + params=[content_type.pk, tag.pk], + ) + + def get_intersection_by_model(self, queryset_or_model, tags): + """ + Create a ``QuerySet`` containing instances of the specified + model associated with *all* of the given list of tags. + """ + tags = get_tag_list(tags) + tag_count = len(tags) + queryset, model = get_queryset_and_model(queryset_or_model) + + if not tag_count: + return model._default_manager.none() + + model_table = qn(model._meta.db_table) + # This query selects the ids of all objects which have all the + # given tags. + query = """ + SELECT %(model_pk)s + FROM %(model)s, %(tagged_item)s + WHERE %(tagged_item)s.content_type_id = %(content_type_id)s + AND %(tagged_item)s.tag_id IN (%(tag_id_placeholders)s) + AND %(model_pk)s = %(tagged_item)s.object_id + GROUP BY %(model_pk)s + HAVING COUNT(%(model_pk)s) = %(tag_count)s""" % { + 'model_pk': '%s.%s' % (model_table, qn(model._meta.pk.column)), + 'model': model_table, + 'tagged_item': qn(self.model._meta.db_table), + 'content_type_id': ContentType.objects.get_for_model(model).pk, + 'tag_id_placeholders': ','.join(['%s'] * tag_count), + 'tag_count': tag_count, + } + + cursor = connection.cursor() + cursor.execute(query, [tag.pk for tag in tags]) + object_ids = [row[0] for row in cursor.fetchall()] + if len(object_ids) > 0: + return queryset.filter(pk__in=object_ids) + else: + return model._default_manager.none() + + def get_union_by_model(self, queryset_or_model, tags): + """ + Create a ``QuerySet`` containing instances of the specified + model associated with *any* of the given list of tags. + """ + tags = get_tag_list(tags) + tag_count = len(tags) + queryset, model = get_queryset_and_model(queryset_or_model) + + if not tag_count: + return model._default_manager.none() + + model_table = qn(model._meta.db_table) + # This query selects the ids of all objects which have any of + # the given tags. + query = """ + SELECT %(model_pk)s + FROM %(model)s, %(tagged_item)s + WHERE %(tagged_item)s.content_type_id = %(content_type_id)s + AND %(tagged_item)s.tag_id IN (%(tag_id_placeholders)s) + AND %(model_pk)s = %(tagged_item)s.object_id + GROUP BY %(model_pk)s""" % { + 'model_pk': '%s.%s' % (model_table, qn(model._meta.pk.column)), + 'model': model_table, + 'tagged_item': qn(self.model._meta.db_table), + 'content_type_id': ContentType.objects.get_for_model(model).pk, + 'tag_id_placeholders': ','.join(['%s'] * tag_count), + } + + cursor = connection.cursor() + cursor.execute(query, [tag.pk for tag in tags]) + object_ids = [row[0] for row in cursor.fetchall()] + if len(object_ids) > 0: + return queryset.filter(pk__in=object_ids) + else: + return model._default_manager.none() + + def get_related(self, obj, queryset_or_model, num=None): + """ + Retrieve a list of instances of the specified model which share + tags with the model instance ``obj``, ordered by the number of + shared tags in descending order. + + If ``num`` is given, a maximum of ``num`` instances will be + returned. + """ + queryset, model = get_queryset_and_model(queryset_or_model) + model_table = qn(model._meta.db_table) + content_type = ContentType.objects.get_for_model(obj) + related_content_type = ContentType.objects.get_for_model(model) + query = """ + SELECT %(model_pk)s, COUNT(related_tagged_item.object_id) AS %(count)s + FROM %(model)s, %(tagged_item)s, %(tag)s, %(tagged_item)s related_tagged_item + WHERE %(tagged_item)s.object_id = %%s + AND %(tagged_item)s.content_type_id = %(content_type_id)s + AND %(tag)s.id = %(tagged_item)s.tag_id + AND related_tagged_item.content_type_id = %(related_content_type_id)s + AND related_tagged_item.tag_id = %(tagged_item)s.tag_id + AND %(model_pk)s = related_tagged_item.object_id""" + if content_type.pk == related_content_type.pk: + # Exclude the given instance itself if determining related + # instances for the same model. + query += """ + AND related_tagged_item.object_id != %(tagged_item)s.object_id""" + query += """ + GROUP BY %(model_pk)s + ORDER BY %(count)s DESC + %(limit_offset)s""" + query = query % { + 'model_pk': '%s.%s' % (model_table, qn(model._meta.pk.column)), + 'count': qn('count'), + 'model': model_table, + 'tagged_item': qn(self.model._meta.db_table), + 'tag': qn(self.model._meta.get_field('tag').rel.to._meta.db_table), + 'content_type_id': content_type.pk, + 'related_content_type_id': related_content_type.pk, + 'limit_offset': num is not None and connection.ops.limit_offset_sql(num) or '', + } + + cursor = connection.cursor() + cursor.execute(query, [obj.pk]) + object_ids = [row[0] for row in cursor.fetchall()] + if len(object_ids) > 0: + # Use in_bulk here instead of an id__in lookup, because id__in would + # clobber the ordering. + object_dict = queryset.in_bulk(object_ids) + return [object_dict[object_id] for object_id in object_ids \ + if object_id in object_dict] + else: + return [] + + +########## +# Models # +########## +def create_intermediary_table_model(model): + """Create an intermediary table model for the specific tag model""" + name = model.__name__ + 'Relation' + + class Meta: + db_table = '%s_relation' % model._meta.db_table + unique_together = (('tag', 'content_type', 'object_id'),) + + def obj_unicode(self): + return u'%s [%s]' % (self.content_type.get_object_for_this_type(pk=self.object_id), self.tag) + + # Set up a dictionary to simulate declarations within a class + attrs = { + '__module__': model.__module__, + 'Meta': Meta, + 'tag': models.ForeignKey(model, verbose_name=_('tag'), related_name='items'), + 'content_type': models.ForeignKey(ContentType, verbose_name=_('content type')), + 'object_id': models.PositiveIntegerField(_('object id'), db_index=True), + 'content_object': generic.GenericForeignKey('content_type', 'object_id'), + '__unicode__': obj_unicode, + } + + return type(name, (models.Model,), attrs) + + +class TagMeta(ModelBase): + "Metaclass for tag models (models inheriting from TagBase)." + def __new__(cls, name, bases, attrs): + model = super(TagMeta, cls).__new__(cls, name, bases, attrs) + if not model._meta.abstract: + # Create an intermediary table and register custom managers for concrete models + intermediary_table_model = create_intermediary_table_model(model) + TagManager(intermediary_table_model).contribute_to_class(model, 'objects') + TaggedItemManager().contribute_to_class(intermediary_table_model, 'objects') + return model + + +class TagBase(models.Model): + """Abstract class to be inherited by model classes.""" + __metaclass__ = TagMeta + + class Meta: + abstract = True + diff --git a/newtagging/utils.py b/newtagging/utils.py new file mode 100644 index 000000000..bfdfecf82 --- /dev/null +++ b/newtagging/utils.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +""" +Tagging utilities - from user tag input parsing to tag cloud +calculation. +""" + + +def get_queryset_and_model(queryset_or_model): + """ + Given a ``QuerySet`` or a ``Model``, returns a two-tuple of + (queryset, model). + + If a ``Model`` is given, the ``QuerySet`` returned will be created + using its default manager. + """ + try: + return queryset_or_model, queryset_or_model.model + except AttributeError: + return queryset_or_model._default_manager.all(), queryset_or_model + + +def get_tag_list(tags): + """ + Utility function for accepting tag input in a flexible manner. + + If a ``Tag`` object is given, it will be returned in a list as + its single occupant. + """ + from newtagging.models import TagBase + if isinstance(tags, TagBase): + return [tags] + else: + return tags + diff --git a/pagination/__init__.py b/pagination/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/pagination/__init__.py @@ -0,0 +1 @@ + diff --git a/pagination/middleware.py b/pagination/middleware.py new file mode 100644 index 000000000..0bab76712 --- /dev/null +++ b/pagination/middleware.py @@ -0,0 +1,10 @@ +class PaginationMiddleware(object): + """ + Inserts a variable representing the current page onto the request object if + it exists in either **GET** or **POST** portions of the request. + """ + def process_request(self, request): + try: + request.page = int(request.REQUEST['page']) + except (KeyError, ValueError): + request.page = 1 \ No newline at end of file diff --git a/pagination/models.py b/pagination/models.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/pagination/models.py @@ -0,0 +1 @@ + diff --git a/pagination/templates/pagination/pagination.html b/pagination/templates/pagination/pagination.html new file mode 100644 index 000000000..3799314e4 --- /dev/null +++ b/pagination/templates/pagination/pagination.html @@ -0,0 +1,25 @@ +{% if is_paginated %} + +{% endif %} diff --git a/pagination/templatetags/__init__.py b/pagination/templatetags/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/pagination/templatetags/__init__.py @@ -0,0 +1 @@ + diff --git a/pagination/templatetags/pagination_tags.py b/pagination/templatetags/pagination_tags.py new file mode 100644 index 000000000..55e5392fe --- /dev/null +++ b/pagination/templatetags/pagination_tags.py @@ -0,0 +1,200 @@ +try: + set +except NameError: + from sets import Set as set +from django import template +from django.db.models.query import QuerySet +from django.core.paginator import Paginator, QuerySetPaginator, InvalidPage + +register = template.Library() + +DEFAULT_PAGINATION = 20 +DEFAULT_WINDOW = 4 +DEFAULT_ORPHANS = 0 + +def do_autopaginate(parser, token): + """ + Splits the arguments to the autopaginate tag and formats them correctly. + """ + split = token.split_contents() + if len(split) == 2: + return AutoPaginateNode(split[1]) + elif len(split) == 3: + try: + paginate_by = int(split[2]) + except ValueError: + raise template.TemplateSyntaxError(u'Got %s, but expected integer.' % split[2]) + return AutoPaginateNode(split[1], paginate_by=paginate_by) + elif len(split) == 4: + try: + paginate_by = int(split[2]) + except ValueError: + raise template.TemplateSyntaxError(u'Got %s, but expected integer.' % split[2]) + try: + orphans = int(split[3]) + except ValueError: + raise template.TemplateSyntaxError(u'Got %s, but expected integer.' % split[3]) + return AutoPaginateNode(split[1], paginate_by=paginate_by, orphans=orphans) + else: + raise template.TemplateSyntaxError('%r tag takes one required argument and one optional argument' % split[0]) + +class AutoPaginateNode(template.Node): + """ + Emits the required objects to allow for Digg-style pagination. + + First, it looks in the current context for the variable specified. This + should be either a QuerySet or a list. + + 1. If it is a QuerySet, this ``AutoPaginateNode`` will emit a + ``QuerySetPaginator`` and the current page object into the context names + ``paginator`` and ``page_obj``, respectively. + + 2. If it is a list, this ``AutoPaginateNode`` will emit a simple + ``Paginator`` and the current page object into the context names + ``paginator`` and ``page_obj``, respectively. + + It will then replace the variable specified with only the objects for the + current page. + + .. note:: + + It is recommended to use *{% paginate %}* after using the autopaginate + tag. If you choose not to use *{% paginate %}*, make sure to display the + list of availabale pages, or else the application may seem to be buggy. + """ + def __init__(self, queryset_var, paginate_by=DEFAULT_PAGINATION, orphans=DEFAULT_ORPHANS): + self.queryset_var = template.Variable(queryset_var) + self.paginate_by = paginate_by + self.orphans = orphans + + def render(self, context): + key = self.queryset_var.var + value = self.queryset_var.resolve(context) + if issubclass(value.__class__, QuerySet): + model = value.model + paginator_class = QuerySetPaginator + else: + value = list(value) + try: + model = value[0].__class__ + except IndexError: + return u'' + paginator_class = Paginator + paginator = paginator_class(value, self.paginate_by, self.orphans) + try: + page_obj = paginator.page(context['request'].page) + except InvalidPage: + context[key] = [] + context['invalid_page'] = True + return u'' + context[key] = page_obj.object_list + context['paginator'] = paginator + context['page_obj'] = page_obj + return u'' + +def paginate(context, window=DEFAULT_WINDOW): + """ + Renders the ``pagination/pagination.html`` template, resulting in a + Digg-like display of the available pages, given the current page. If there + are too many pages to be displayed before and after the current page, then + elipses will be used to indicate the undisplayed gap between page numbers. + + Requires one argument, ``context``, which should be a dictionary-like data + structure and must contain the following keys: + + ``paginator`` + A ``Paginator`` or ``QuerySetPaginator`` object. + + ``page_obj`` + This should be the result of calling the page method on the + aforementioned ``Paginator`` or ``QuerySetPaginator`` object, given + the current page. + + This same ``context`` dictionary-like data structure may also include: + + ``getvars`` + A dictionary of all of the **GET** parameters in the current request. + This is useful to maintain certain types of state, even when requesting + a different page. + """ + try: + paginator = context['paginator'] + page_obj = context['page_obj'] + page_range = paginator.page_range + # First and last are simply the first *n* pages and the last *n* pages, + # where *n* is the current window size. + first = set(page_range[:window]) + last = set(page_range[-window:]) + # Now we look around our current page, making sure that we don't wrap + # around. + current_start = page_obj.number-1-window + if current_start < 0: + current_start = 0 + current_end = page_obj.number-1+window + if current_end < 0: + current_end = 0 + current = set(page_range[current_start:current_end]) + pages = [] + # If there's no overlap between the first set of pages and the current + # set of pages, then there's a possible need for elusion. + if len(first.intersection(current)) == 0: + first_list = sorted(list(first)) + second_list = sorted(list(current)) + pages.extend(first_list) + diff = second_list[0] - first_list[-1] + # If there is a gap of two, between the last page of the first + # set and the first page of the current set, then we're missing a + # page. + if diff == 2: + pages.append(second_list[0] - 1) + # If the difference is just one, then there's nothing to be done, + # as the pages need no elusion and are correct. + elif diff == 1: + pass + # Otherwise, there's a bigger gap which needs to be signaled for + # elusion, by pushing a None value to the page list. + else: + pages.append(None) + pages.extend(second_list) + else: + pages.extend(sorted(list(first.union(current)))) + # If there's no overlap between the current set of pages and the last + # set of pages, then there's a possible need for elusion. + if len(current.intersection(last)) == 0: + second_list = sorted(list(last)) + diff = second_list[0] - pages[-1] + # If there is a gap of two, between the last page of the current + # set and the first page of the last set, then we're missing a + # page. + if diff == 2: + pages.append(second_list[0] - 1) + # If the difference is just one, then there's nothing to be done, + # as the pages need no elusion and are correct. + elif diff == 1: + pass + # Otherwise, there's a bigger gap which needs to be signaled for + # elusion, by pushing a None value to the page list. + else: + pages.append(None) + pages.extend(second_list) + else: + pages.extend(sorted(list(last.difference(current)))) + to_return = { + 'pages': pages, + 'page_obj': page_obj, + 'paginator': paginator, + 'is_paginated': paginator.count > paginator.per_page, + } + if 'request' in context: + getvars = context['request'].GET.copy() + if 'page' in getvars: + del getvars['page'] + if len(getvars.keys()) > 0: + to_return['getvars'] = "&%s" % getvars.urlencode() + else: + to_return['getvars'] = '' + return to_return + except KeyError: + return {} +register.inclusion_tag('pagination/pagination.html', takes_context=True)(paginate) +register.tag('autopaginate', do_autopaginate) \ No newline at end of file diff --git a/pagination/tests.py b/pagination/tests.py new file mode 100644 index 000000000..837e55cfe --- /dev/null +++ b/pagination/tests.py @@ -0,0 +1,52 @@ +""" +>>> from django.core.paginator import Paginator +>>> from pagination.templatetags.pagination_tags import paginate +>>> from django.template import Template, Context + +>>> p = Paginator(range(15), 2) +>>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] +[1, 2, 3, 4, 5, 6, 7, 8] + +>>> p = Paginator(range(17), 2) +>>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] +[1, 2, 3, 4, 5, 6, 7, 8, 9] + +>>> p = Paginator(range(19), 2) +>>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] +[1, 2, 3, 4, None, 7, 8, 9, 10] + +>>> p = Paginator(range(21), 2) +>>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] +[1, 2, 3, 4, None, 8, 9, 10, 11] + +# Testing orphans +>>> p = Paginator(range(5), 2, 1) +>>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] +[1, 2] + +>>> p = Paginator(range(21), 2, 1) +>>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] +[1, 2, 3, 4, None, 7, 8, 9, 10] + +>>> t = Template("{% load pagination_tags %}{% autopaginate var 2 %}{% paginate %}") + +# WARNING: Please, please nobody read this portion of the code! +>>> class GetProxy(object): +... def __iter__(self): yield self.__dict__.__iter__ +... def copy(self): return self +... def urlencode(self): return u'' +... def keys(self): return [] +>>> class RequestProxy(object): +... page = 1 +... GET = GetProxy() +>>> +# ENDWARNING + +>>> t.render(Context({'var': range(21), 'request': RequestProxy()})) +u'\\n