2

我目前正在研究我自制的标题系统。因此,我尝试使用#_1#-#_4#在文本中进行编号,然后将其转换为标题。因此,您将标题的文本写在数字和第二个之间#。例如:

#_1Testheadline#
#_2second headline under the first one#
#_2another headline under the first one#
#_1second headline (not under the first one)#

会成为

1. Testheadline
1.1 second headline under the first one
1.2 another headline under the first one
2. second headline (not under the first one)

希望你明白我的意思。

所以第一个例子(所以#_1#在里面)是用 WYSIWYG-Editor 编写的,所以这是普通的 html 代码,然后存储在数据库中的变量中。

我现在想要的是当我从数据库中获取这个变量时,我想用真实的标题(查看)替换所有的伪标题,所以第一个例子将变成第二个。

因此,我需要找到所有出现的#_1,替换为<h1>,一直到 ,#然后替换为</h1>。标题的第二、第三和第四“层”相同。如果我能做到这一点,我仍然不会完成,因为现在,标题需要它们的数字在前面,因此我可以简单地使用 4 个计数器:

var firstlayercount = 0,
  secondlayercount = 0;
var thirdlayercount = 0,
  fourthlayercount = 0;

并增加并将它们设置回 0,具体取决于找到的标题,所以实际上这应该是更容易的部分。但更难的问题是,如何#_1在字符串中找到,替换它,然后去#替换它呢?并多次这样做?

4

1 回答 1

2

使用 preg_replace_callback 函数

$str = '#_1Testheadline#
#_2second headline under the first one
#_2another headline under the first one
#_1second headline (not under the first one)';

// Current level
$level = 0;
echo preg_replace_callback('/#?\s*#_(\d)+/', 
  function($x) use (&$level) {
    // Close previous tag if it is
    $out = ($level ?  "</h{$level}>\n" : '');
    // Save current level and open tag  
    $level = $x[1];
    return $out .  "<h{$level}>"; 
  },
  // Don't forget to close the last tag
  $str) . "<h{$level}>";

结果

<h1>Testheadline#</h1>
<h2>second headline under the first one</h2>
<h2>another headline under the first one</h2>
<h1>second headline (not under the first one)<h1>  

更新 1

您可以使用相同的方法来构建有序列表

$level = 0;

echo preg_replace_callback('/#?\s*#_(\d)+/', 
  function($x) use (&$level) { 
    if($x[1] > $level) $out = "\n<ol>\n";
    else if ($x[1] < $level) $out = "</li>\n</ol>\n";
    else $out = "</li>\n";
    $level = $x[1];
    return $out .  "<li>"; 
  },
  $str) . "</li>\n</ol>\n";

结果

<ol>
   <li>Testheadline#
   <ol>
      <li>second headline under the first one</li>
      <li>another headline under the first one</li>
  </ol>
  <li>second headline (not under the first one)</li>
</ol>

更新 2

通过 css 样式化列表

<STYLE>
ol {
  list-style: none; 
  counter-reset: li; 
}
li:before {
   counter-increment: li; 
   content: counters(li,".") ". "; 
}
</STYLE>
<ol>
   <li>Testheadline#
   <ol>
      <li>second headline under the first one</li>
      <li>another headline under the first one</li>
  </ol>
  <li>second headline (not under the first one)</li>
</ol>


更新 3

用php进行编号

$cnts = [ 0 ];
echo preg_replace_callback('/#?\s*#_(\d)+/', 
  function($x) use (&$cnts) {
    $level = $x[1]-1;
    if($level < count($cnts)-1) $cnts = array_slice($cnts, 0, $level+1);
    if (! isset($cnts[$level])) $cnts[$level] = 1;
    else $cnts[$level]++;
    $temp = array_slice($cnts, 0, $level+1);
    return "\n" . implode('.', $temp) . ". "; 
  },
  $str) ;

结果

1. Testheadline
1.1. second headline under the first one
1.2. another headline under the first one
2. second headline (not under the first one)
于 2018-01-29T07:26:01.123 回答