2009-02-11 17 views
8

के लिए एक टीज़र/अंश प्राप्त करें मेरे पास एक पृष्ठ है जो समाचार लेखों की सूची देगा। पृष्ठ की लंबाई को कम करने के लिए, मैं केवल एक टीज़र (लेख के पहले 200 शब्द/600 अक्षरों) को प्रदर्शित करना चाहता हूं और फिर "अधिक ..." लिंक प्रदर्शित करना चाहता हूं, जब क्लिक किया गया, तो शेष का विस्तार होगा एक jQuery/जावास्क्रिप्ट तरीके में आलेख। अब, मेरे पास कुछ पेस्ट पेज पर निम्न सहायक विधि भी मिली है, जो यह सुनिश्चित करेगी कि समाचार लेख (स्ट्रिंग) को किसी शब्द के बीच में कटाई नहीं किया गया है:रेल: एक लेख

def shorten (string, count = 30) 
    if string.length >= count 
     shortened = string[0, count] 
     splitted = shortened.split(/\s/) 
     words = splitted.length 
     splitted[0, words-1].join(" ") + ' ...' 
    else 
     string 
    end 
    end 

मेरी समस्या यह है कि डीबी से प्राप्त समाचार आलेख निकायों को HTML स्वरूपित किया गया है। तो अगर मैं दुर्भाग्यपूर्ण हूं, तो उपरोक्त सहायक मेरे लेख स्ट्रिंग को एचटीएमएल टैग के बीच में काट देगा और वहां "अधिक ..." स्ट्रिंग डालेंगे (उदाहरण के लिए ""), जो पृष्ठ पर मेरा एचटीएमएल दूषित करेगा ।

क्या इसके आसपास कोई रास्ता है या वहां कोई प्लगइन है जिसका उपयोग मैं HTML स्ट्रिंग से अंश/टीज़र उत्पन्न करने के लिए कर सकता हूं?

उत्तर

2

आपके उत्तरों के लिए बहुत बहुत धन्यवाद! हालांकि, इस बीच में मैंने jQuery HTML Truncator plugin पर ठोकर खाई, जो मेरे उद्देश्यों को पूरी तरह से फिट करती है और ग्राहक-पक्ष में छंटनी को बदल देती है।यह कोई आसान नहीं मिलता है :-)

1

यदि आप HTML तत्वों के बीच में विभाजित नहीं करना चाहते हैं तो आपको अधिक जटिल पार्सर्स लिखना होगा। यह याद रखना होगा कि यह <> ब्लॉक के बीच में है और यदि यह दो टैग के बीच है।

भले ही आपने ऐसा किया हो, आपको अभी भी समस्याएं होंगी। अगर कुछ पूरे लेख को एक HTML तत्व में डाल देते हैं, क्योंकि पार्सर इसे खोने वाले टैग के कारण कहीं भी विभाजित नहीं कर सका।

यदि यह संभव है तो मैं लेखों में कोई टैग न डालने की कोशिश करता हूं या टैग में रखता हूं जिसमें कुछ भी नहीं होता है (<div> और इसी तरह)।

def shorten (string, count = 30) 
    if string.length >= count 
     shortened = string[0, count] 
     splitted = shortened.split(/\s/) 
     words = splitted.length 
     if(splitted[words-1].include? "<") 
     splitted[0,words-2].join(" ") + ' ...' 
     else 
     splitted[0, words-1].join(" ") + ' ...' 
    else 
     string 
    end 
    end 
3

My answer here काम करना चाहिए: यदि आप एक टैग जो बहुत सरल है के बीच में हैं कि जिस तरह से आप केवल होता जाँच करने के लिए। मूल प्रश्न (गलती, मेरे द्वारा पूछा गया) मार्कडाउन को कम करने के बारे में था, लेकिन मैंने मार्कडाउन को एचटीएमएल में परिवर्तित कर दिया और फिर इसे छोटा कर दिया, इसलिए इसे काम करना चाहिए।

बेशक यदि आपकी साइट को अधिक ट्रैफ़िक मिलता है, तो आपको अंश को कैश करना चाहिए (शायद जब पोस्ट बनाया/अपडेट किया गया हो, तो आप डेटाबेस में अंश संग्रहीत कर सकते हैं?), इसका मतलब यह भी होगा कि आप उपयोगकर्ता को संशोधित करने की अनुमति दे सकते हैं

>> puts "<p><b><a href=\"hi\">Something</a></p>".truncate_html(5, at_end = "...") 
=> <p><b><a href="hi">Someth...</a></b></p> 

..और कोड (अन्य जवाब से नकल):

require 'rexml/parsers/pullparser' 

class String 
    def truncate_html(len = 30, at_end = nil) 
    p = REXML::Parsers::PullParser.new(self) 
    tags = [] 
    new_len = len 
    results = '' 
    while p.has_next? && new_len > 0 
     p_e = p.pull 
     case p_e.event_type 
     when :start_element 
     tags.push p_e[0] 
     results << "<#{tags.last}#{attrs_to_s(p_e[1])}>" 
     when :end_element 
     results << "</#{tags.pop}>" 
     when :text 
     results << p_e[0][0..new_len] 
     new_len -= p_e[0].length 
     else 
     results << "<!-- #{p_e.inspect} -->" 
     end 
    end 
    if at_end 
     results << "..." 
    end 
    tags.reverse.each do |tag| 
     results << "</#{tag}>" 
    end 
    results 
    end 

    private 

    def attrs_to_s(attrs) 
    if attrs.empty? 
     '' 
    else 
     ' ' + attrs.to_a.map { |attr| %{#{attr[0]}="#{attr[1]}"} }.join(' ') 
    end 
    end 
end 
+0

ओह मुझे तुम्हारी पसंद है, यह पाठ – LDomagala

15

आपके संयोजन का उपयोग कर सकते हैं या अपने स्वयं के अंश

प्रयोग में प्रवेशऔर Truncate

truncate("And they found that many people were sleeping better.", 
    :omission => "... (continued)", :length => 15) 
# => And they found... (continued) 

मैं ऐसा ही काम कर रहा हूं जहां मेरे पास ब्लॉग पोस्ट हैं और मैं बस एक त्वरित अंश दिखाना चाहता हूं। तो मेरे विचार में मैं बस कार्य करें:

sanitize(truncate(blog_post.body, length: 150)) 

बाहर स्ट्रिप्स कि HTML टैग, मुझे पहले 150 वर्ण देता है और ध्यान में रखते हुए नियंत्रित किया जाता है तो यह MVC अनुकूल है।

शुभकामनाएं!

+5

के आसपास टैग के साथ समस्या को हल करता है यह काम कर सकता है, लेकिन आपको sanitize और फिर छंटनी चाहिए। यदि आप छंटनी करते हैं और फिर sanitize, तो आप एक HTML टैग के बीच में छंटनी कर सकते हैं और sanitize आंशिक टैग दृश्यमान छोड़ देंगे। –

1

मैं HTML को स्वच्छ कर दूंगा और पहली वाक्य निकाल दूंगा। मान लिया जाये कि आप एक लेख मॉडल है, एक 'शरीर' विशेषता है कि HTML शामिल साथ:

# lib/core_ext/string.rb 
class String 
    def first_sentence 
    self[/(\A[^.|!|?]+)/, 1] 
    end 
end 

# app/models/article.rb 
def teaser 
    HTML::FullSanitizer.new.sanitize(body).first_sentence 
end 

यह बदल जाएगा "< b> यह </b> एक < em> महत्वपूर्ण </em> लेख और! यहां बाकी लेख है। " "यह एक महत्वपूर्ण लेख है" में।

+0

इसके लिए बंदर पैचिंग स्ट्रिंग थोड़ा अधिक है ... – DGM

0

मैं इस का उपयोग करते हुए निम्नलिखित समाधान

हल मणि स्थापित करें 'स्वच्छ'

gem install sanitize 

और इस्तेमाल किया कोड के बाद, यहाँ शरीर पाठ वाले html टैग है।

<%= content_tag :div, Sanitize.clean(truncate(body, length: 200, separator: ' ', omission: "... #{ link_to '(continue)', '#' }"), Sanitize::Config::BASIC).html_safe %> 

मान्य एचटीएमएल के साथ उद्धरण देता है। मुझे उम्मीद है कि यह किसी की मदद करेगा।

0

अब HTMLTruncator नामक एक मणि है जो आपके लिए इसका ख्याल रखता है। मैंने इसे पोस्ट अंश और इस तरह प्रदर्शित करने के लिए उपयोग किया है, और यह बहुत मजबूत है।

संबंधित मुद्दे