Home 게시판 커뮤니티 Q&A 필터(filter) 관련 질문입니다.

8개 답변, 2 voices Last updated by Avatar of 082net082net 18 years, 3 months 전
  • Avatar of 무시못할석2무시못할석2
    Participant
    @무시못할석2
    #1996

    정말 감사합니다. ^^;
    적용해보니 잘 됩니다.

    Avatar of 무시못할석2무시못할석2
    Participant
    @무시못할석2
    #1997

    워드프레스의 code 태그 기능이 소스를 표현하기에 부적당한것 같아서 dp.SyntaxHighlighter를 적용했습니다. dp.SyntaxHighlighter는 제 블로그에 쓴 글처럼 소스 등을 보기 좋게 해주는 것인데, 포스팅 내용에 <textarea name="code" … >와 </textarea> 사이의 내용을 자스를 통해 변환시켜줍니다.

    그런데 그냥 textarea를 하니 function-formatting.php에 있는 autop()함수에 의해 글을 뿌려주면서 자동으로 p 와 br 태그를 덧붙여버리더군요. 그래서 아래와 같이 플러그인을 제작해봤습니다.

    if (!function_exists('clean_textarea')) {
    function clean_textarea($text) {
       $text = str_replace('<br />', '', $text);
       $text = str_replace('<p>', "n", $text);
       $text = str_replace('</p>', '', $text);
       return $text;
    }
    }

    if (!function_exists('convert_textarea')) {
    function convert_textarea($pee) {
    $pee = preg_replace('!(<textarea name="code.*?>)(.*?)</textarea>!ise', " stripslashes('$1') .  stripslashes(clean_textarea('$2'))  . '</textarea>' ", $pee);
    return $pee;
    }
    }

    add_action('init', 'clean_textarea');
    add_action('init', 'convert_textarea');
    add_filter('the_content', 'convert_textarea');

    근데 문제는 clean_textarea() 함수에서 p와 br태그를 제거하도록 했는데, 문제는 소스중에 p나 br이 포함되어 있더라도 그냥 제거해버리는 것 같습니다. 제 생각엔 autop()함수에 의해 추가된 p나 br 태그만 제거하도록 하면 될 것 같은데, 어떤 방법이 없을까요?

    아래는 제가 참고한 function-formatting.php에 있는 autop()함수와 그와 관련해서 clean_pre()함수의 내용입니다. 참고로 같이 올려봤습니다.

    function clean_pre($text) {
       $text = str_replace('<br />', '', $text);
       $text = str_replace('<p>', "n", $text);
       $text = str_replace('</p>', '', $text);
       return $text;
    }

    function wpautop($pee, $br = 1) {
       $pee = $pee // . "n"; // just to make things a little easier, pad the end
       $pee = preg_replace('|<br />s*<br />|', "nn", $pee);
       // Space things out a little
       $pee = preg_replace('!(<(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)!', "n$1", $pee);
       $pee = preg_replace('!(</(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])>)!', "$1nn", $pee);
       $pee = str_replace(array("rn", "r"), "n", $pee); // cross-platform newlines
       $pee = preg_replace("/nn+/", "nn", $pee); // take care of duplicates
       $pee = preg_replace('/n?(.+?)(?:ns*n|z)/s', "<p>$1</p>n", $pee); // make paragraphs, including one at the end
       $pee = preg_replace('|<p>s*?</p>|', '', $pee); // under certain strange conditions it could create a P of entirely whitespace
       $pee = preg_replace('!<p>s*(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|hr|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)s*</p>!', "$1", $pee); // don't pee all over a tag
       $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problem with nested lists
       $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee);
       $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
       $pee = preg_replace('!<p>s*(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|hr|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)!', "$1", $pee);
       $pee = preg_replace('!(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)s*</p>!', "$1", $pee);
       if ($br) $pee = preg_replace('|(?<!<br />)s*n|', "<br />n", $pee); // optionally make line breaks
       $pee = preg_replace('!(</?(?:table|thead|tfoot|caption|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)s*<br />!', "$1", $pee);
       $pee = preg_replace('!<br />(s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)!', '$1', $pee);
       $pee = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '</pre>' ", $pee);
       
       return $pee;
    }

    ps : 코드 부분 때문에 폭이 너무 넓어져서 읽기가 어렵게 돼버렸습니다. 보기좋게 해야되는데, 중간에 엔터로 구분을 하니 코드 해독이 난이해질 수 있을 것 같아 그냥 뒀습니다. 죄송합니다.

    Avatar of 무시못할석2무시못할석2
    Participant
    @무시못할석2
    #2001

    워드프레스의 code 태그 기능이 소스를 표현하기에 부적당한것 같아서 dp.SyntaxHighlighter를 적용했습니다. dp.SyntaxHighlighter는 제 블로그에 쓴 글처럼 소스 등을 보기 좋게 해주는 것인데, 포스팅 내용에 <textarea name="code" … >와 </textarea> 사이의 내용을 자스를 통해 변환시켜줍니다.

    그런데 그냥 textarea를 하니 function-formatting.php에 있는 autop()함수에 의해 글을 뿌려주면서 자동으로 p 와 br 태그를 덧붙여버리더군요. 그래서 아래와 같이 플러그인을 제작해봤습니다.

    if (!function_exists('clean_textarea')) {
    function clean_textarea($text) {
       $text = str_replace('<br />', '', $text);
       $text = str_replace('<p>', "n", $text);
       $text = str_replace('</p>', '', $text);
       return $text;
    }
    }

    if (!function_exists('convert_textarea')) {
    function convert_textarea($pee) {
    $pee = preg_replace('!(<textarea name="code.*?>)(.*?)</textarea>!ise', " stripslashes('$1') .  stripslashes(clean_textarea('$2'))  . '</textarea>' ", $pee);
    return $pee;
    }
    }

    add_action('init', 'clean_textarea');
    add_action('init', 'convert_textarea');
    add_filter('the_content', 'convert_textarea');

    근데 문제는 clean_textarea() 함수에서 p와 br태그를 제거하도록 했는데, 문제는 소스중에 p나 br이 포함되어 있더라도 그냥 제거해버리는 것 같습니다. 제 생각엔 autop()함수에 의해 추가된 p나 br 태그만 제거하도록 하면 될 것 같은데, 어떤 방법이 없을까요?

    아래는 제가 참고한 function-formatting.php에 있는 autop()함수와 그와 관련해서 clean_pre()함수의 내용입니다. 참고로 같이 올려봤습니다.

    function clean_pre($text) {
       $text = str_replace('<br />', '', $text);
       $text = str_replace('<p>', "n", $text);
       $text = str_replace('</p>', '', $text);
       return $text;
    }

    function wpautop($pee, $br = 1) {
       $pee = $pee // . "n"; // just to make things a little easier, pad the end
       $pee = preg_replace('|<br />s*<br />|', "nn", $pee);
       // Space things out a little
       $pee = preg_replace('!(<(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)!', "n$1", $pee);
       $pee = preg_replace('!(</(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])>)!', "$1nn", $pee);
       $pee = str_replace(array("rn", "r"), "n", $pee); // cross-platform newlines
       $pee = preg_replace("/nn+/", "nn", $pee); // take care of duplicates
       $pee = preg_replace('/n?(.+?)(?:ns*n|z)/s', "<p>$1</p>n", $pee); // make paragraphs, including one at the end
       $pee = preg_replace('|<p>s*?</p>|', '', $pee); // under certain strange conditions it could create a P of entirely whitespace
       $pee = preg_replace('!<p>s*(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|hr|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)s*</p>!', "$1", $pee); // don't pee all over a tag
       $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problem with nested lists
       $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee);
       $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
       $pee = preg_replace('!<p>s*(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|hr|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)!', "$1", $pee);
       $pee = preg_replace('!(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)s*</p>!', "$1", $pee);
       if ($br) $pee = preg_replace('|(?<!<br />)s*n|', "<br />n", $pee); // optionally make line breaks
       $pee = preg_replace('!(</?(?:table|thead|tfoot|caption|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)s*<br />!', "$1", $pee);
       $pee = preg_replace('!<br />(s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)!', '$1', $pee);
       $pee = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '</pre>' ", $pee);
       
       return $pee;
    }

    ps : 코드 부분 때문에 폭이 너무 넓어져서 읽기가 어렵게 돼버렸습니다. 보기좋게 해야되는데, 중간에 엔터로 구분을 하니 코드 해독이 난이해질 수 있을 것 같아 그냥 뒀습니다. 죄송합니다.

    Avatar of 082net082net
    Keymaster
    @082net
    #1998

    autop 문제는 해결하기가 참 난감한 문제더군요. 지금까지 제 나름대로의 해결법은 필터(apply_filter)기능을 사용하는 플러그인들의 우선순의를 조절하는것과, 치환하는 함수에 줄건너뛰기(n)를 넣는 방법이었습니다.

    하지만 이 경우는 본문이 완전히 로딩된 후에 자바스크립트를 이용해 내용을 치환하기 때문에 다른 해결법을 취해야 할 듯 하네요. (자바스크립트가 꺼진 브라우저에서는 어떻게 표현 되나요??)

    잠깐 생각이 드는 방법은 autop 필터가 적용되기 전에 본문 중 textarea부분을 살짝 빼 놓았다가, autop가 적용된 이후에 다시 치환하는것인데… 좀 복잡해 질것같은 예감이 엄습하는군요.

    Array 속성을 가진 변수를 하나 만들어서 function 1() 에서 불러와서 autop가 적용되기 전에 값들을 저장 해 놓은 다음, autop가 적용된 이후에 그 변수를 불러와서 function 2()에서 다시 치환하는거죠.

    $myTextArea_Codes = array();
    $textarea_replace_count = 0;

    function get_codes_before_autop($text){
    $text = preg_replace('preg', 'replace_codes_before_autop('1')', $text);
    return $text;
    }

    function replace_codes_before_autop($code){
    global $myTextArea_Codes, $textarea_replace_count, $post;
    $myTextArea_Codes[] = $code;
    $new_code = "<p>[textareacode:".$post->ID."-".$textarea_replace_count."]</p>";
    $textarea_replace_count++;
    return $new_code;
    }

    function restore_after_autop($text){
    global $myTextArea_Codes, $post;
    preg_match_all('preg', $text, $match);
    $match = $match[0];
    foreach(.....){
    내용들....
    }
    }

    add_filter('the_content', 'get_codes_before_autop', 0);
    add_filter('the_content', 'restore_after_autop', 20);

    얼추 이런식의 생각인데… 근거가 아예 없지는 않지만, 테스트 해 본게 아니라서 적용 가능할지는 확실치 않은데다… 좀 억지스러움이 물씬 풍기기 때문에 추천할 만한 방법은 아니네요… ^^;

    preg_replace방식이기때문에… 따옴표나 역슬래쉬()에 대한 대책들도 포함되어야 할겁니다.

    autop와 관련해서 다른 경험을 가진 분께서 또 다른 방법을 제시해주시면 좋겠네요.

    참… 어떤 플러그인에서는 autop필터를 제거했다가 다시 추가하는 방법을 쓰기도 하더군요.(찾아보니 extreme video 플러그인 이었네요)

    if(function_exists('wpautop')){
          remove_filter('the_content','wpautop');
          add_filter('the_content','wpautop',8);
    }

    Avatar of 082net
    Facebook 사용자 모임 그룹 도 함께 운영되고 있으며, 격 주로 미트업과 스터디를 진행하고 있으니 관심 있으신 분들의 많은 참여 바랍니다 🙂
    Avatar of 082net082net
    Keymaster
    @082net
    #2002

    autop 문제는 해결하기가 참 난감한 문제더군요. 지금까지 제 나름대로의 해결법은 필터(apply_filter)기능을 사용하는 플러그인들의 우선순의를 조절하는것과, 치환하는 함수에 줄건너뛰기(n)를 넣는 방법이었습니다.

    하지만 이 경우는 본문이 완전히 로딩된 후에 자바스크립트를 이용해 내용을 치환하기 때문에 다른 해결법을 취해야 할 듯 하네요. (자바스크립트가 꺼진 브라우저에서는 어떻게 표현 되나요??)

    잠깐 생각이 드는 방법은 autop 필터가 적용되기 전에 본문 중 textarea부분을 살짝 빼 놓았다가, autop가 적용된 이후에 다시 치환하는것인데… 좀 복잡해 질것같은 예감이 엄습하는군요.

    Array 속성을 가진 변수를 하나 만들어서 function 1() 에서 불러와서 autop가 적용되기 전에 값들을 저장 해 놓은 다음, autop가 적용된 이후에 그 변수를 불러와서 function 2()에서 다시 치환하는거죠.

    $myTextArea_Codes = array();
    $textarea_replace_count = 0;

    function get_codes_before_autop($text){
    $text = preg_replace('preg', 'replace_codes_before_autop('1')', $text);
    return $text;
    }

    function replace_codes_before_autop($code){
    global $myTextArea_Codes, $textarea_replace_count, $post;
    $myTextArea_Codes[] = $code;
    $new_code = "<p>[textareacode:".$post->ID."-".$textarea_replace_count."]</p>";
    $textarea_replace_count++;
    return $new_code;
    }

    function restore_after_autop($text){
    global $myTextArea_Codes, $post;
    preg_match_all('preg', $text, $match);
    $match = $match[0];
    foreach(.....){
    내용들....
    }
    }

    add_filter('the_content', 'get_codes_before_autop', 0);
    add_filter('the_content', 'restore_after_autop', 20);

    얼추 이런식의 생각인데… 근거가 아예 없지는 않지만, 테스트 해 본게 아니라서 적용 가능할지는 확실치 않은데다… 좀 억지스러움이 물씬 풍기기 때문에 추천할 만한 방법은 아니네요… ^^;

    preg_replace방식이기때문에… 따옴표나 역슬래쉬()에 대한 대책들도 포함되어야 할겁니다.

    autop와 관련해서 다른 경험을 가진 분께서 또 다른 방법을 제시해주시면 좋겠네요.

    참… 어떤 플러그인에서는 autop필터를 제거했다가 다시 추가하는 방법을 쓰기도 하더군요.(찾아보니 extreme video 플러그인 이었네요)

    if(function_exists('wpautop')){
          remove_filter('the_content','wpautop');
          add_filter('the_content','wpautop',8);
    }

    Avatar of 082net
    Facebook 사용자 모임 그룹 도 함께 운영되고 있으며, 격 주로 미트업과 스터디를 진행하고 있으니 관심 있으신 분들의 많은 참여 바랍니다 🙂
    Avatar of 무시못할석2무시못할석2
    Participant
    @무시못할석2
    #1999

    082님 매번 감사합니다.
    082님이 알려주신 내용을 근거로 조금 더 공부해야 되겠습니다.
    아직 답변 내용을 다 이해하기에는 제 지식수준이 넘 낮은것 같습니다.
    좋은 하루되십시오.. *^^*

    Avatar of 무시못할석2무시못할석2
    Participant
    @무시못할석2
    #2003

    082님 매번 감사합니다.
    082님이 알려주신 내용을 근거로 조금 더 공부해야 되겠습니다.
    아직 답변 내용을 다 이해하기에는 제 지식수준이 넘 낮은것 같습니다.
    좋은 하루되십시오.. *^^*

    Avatar of 082net082net
    Keymaster
    @082net
    #2000

    음… 오늘 다시 이 글을 보면서 생각난게 있어서 적어봅니다.

    위의 내용보다는 좀 더 간단하게 처리 할 수도 있는 방법입니다.

    function Pass_AutoP_Codes($text) {
       preg_match_all('/(<textarea(.*?)name="code(.*?)>(.*?)</textarea>)/ise', $text, $match);
       $match = $match[0];
       $codes = array();
       if(!empty($match)) {//textarea 코드부분이 있으면 잠시 바꿔놓습니다.
          for($i=0; $i<count($match); $i++) {
             //autop에서 <p>태그를 추가하지 않도록 <p>를 넣어놓습니다.
             $text = str_replace($match[$i], '<p>[textarea:'.$i.']</p>', $text);
             $codes[] = $match[$i];
          }
       }
       //autop를 적용합니다.
       $text = wpautop($text);
       if(!empty($codes)) {//autop 처리 후 다시 원래의 코드를 넣습니다.
          for($i=0; $i<count($codes); $i++) {
             $text = str_replace('<p>[textarea:'.$i.']</p>', $codes[$i], $text);
          }
       }
       return $text;
    }

    remove_filter('the_content', 'wpautop');
    remove_filter('the_excerpt', 'wpautop');
    remove_filter('comment_text', 'wpautop');

    add_filter('the_content', 'Pass_AutoP_Codes');
    add_filter('the_excerpt', 'Pass_AutoP_Codes');
    add_filter('comment_text', 'Pass_AutoP_Codes');

    Pass_AutoP_Codes라는 이름은 임의로 넣은것입니다.
    제가 preg 관련 함수와 정규식에대한 지식이 없어서 찾을 preg 부분에 확신이 없군요. 잘 아시는 분께서 보완해 주시면 좋겠습니다.

    Avatar of 082net
    Facebook 사용자 모임 그룹 도 함께 운영되고 있으며, 격 주로 미트업과 스터디를 진행하고 있으니 관심 있으신 분들의 많은 참여 바랍니다 🙂
    Avatar of 082net082net
    Keymaster
    @082net
    #2004

    음… 오늘 다시 이 글을 보면서 생각난게 있어서 적어봅니다.

    위의 내용보다는 좀 더 간단하게 처리 할 수도 있는 방법입니다.

    function Pass_AutoP_Codes($text) {
       preg_match_all('/(<textarea(.*?)name="code(.*?)>(.*?)</textarea>)/ise', $text, $match);
       $match = $match[0];
       $codes = array();
       if(!empty($match)) {//textarea 코드부분이 있으면 잠시 바꿔놓습니다.
          for($i=0; $i<count($match); $i++) {
             //autop에서 <p>태그를 추가하지 않도록 <p>를 넣어놓습니다.
             $text = str_replace($match[$i], '<p>[textarea:'.$i.']</p>', $text);
             $codes[] = $match[$i];
          }
       }
       //autop를 적용합니다.
       $text = wpautop($text);
       if(!empty($codes)) {//autop 처리 후 다시 원래의 코드를 넣습니다.
          for($i=0; $i<count($codes); $i++) {
             $text = str_replace('<p>[textarea:'.$i.']</p>', $codes[$i], $text);
          }
       }
       return $text;
    }

    remove_filter('the_content', 'wpautop');
    remove_filter('the_excerpt', 'wpautop');
    remove_filter('comment_text', 'wpautop');

    add_filter('the_content', 'Pass_AutoP_Codes');
    add_filter('the_excerpt', 'Pass_AutoP_Codes');
    add_filter('comment_text', 'Pass_AutoP_Codes');

    Pass_AutoP_Codes라는 이름은 임의로 넣은것입니다.
    제가 preg 관련 함수와 정규식에대한 지식이 없어서 찾을 preg 부분에 확신이 없군요. 잘 아시는 분께서 보완해 주시면 좋겠습니다.

    Avatar of 082net
    Facebook 사용자 모임 그룹 도 함께 운영되고 있으며, 격 주로 미트업과 스터디를 진행하고 있으니 관심 있으신 분들의 많은 참여 바랍니다 🙂
9 글 보임 - 1에서 9 까지 (총 9 중에서)
  • 답변은 로그인 후 가능합니다.