February 18, 2014
纽约时报网站改版背后的web技术
"\u003cp\u003e\u003ca href=\"http://blog.haohtml.com/wp-content/uploads/2014/02/nytimes-redesign.png\"\u003e\u003cimg src=\"http://blog.haohtml.com/wp-content/uploads/2014/02/nytimes-redesign.png\" alt=\"nytimes-redesign\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e原文地址: \u003ca href=\"http://open.blogs.nytimes.com/2014/01/08/the-technology-behind-the-nytimes-com-redesign/?_php=true\u0026amp;_type=blogs\u0026amp;_php=true\u0026amp;_type=blogs\u0026amp;_r=1\"\u003e“The Technology Behind the NYTimes.com Redesign”\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e纽约时报英文网站今年进行了一次改版,这次改版不仅仅是给一艘大船重新刷了遍油漆那么简单,除了外观上的重新设计,我们也对代码进行了大量的重构,采用了新的框架,让网站更快,也为以后代码的维护、升级便利性进行了重新设计。 \u003ca href=\"https://twitter.com/remmons\"\u003eReed Emmons\u003c/a\u003e,是这次改版的负责人,在这篇文章将分享我们如何让纽约时报这首老船更快更酷。\u003c/p\u003e\n\u003cp\u003e很少有机会能够在像纽约时报这么老资格和规模的网站进行一场「从头来过」的重构和设计工作,我这里说的从头来过,不仅仅是视觉设计上的重新设计,更是一个重新发明整个数码传媒平台。纽约时报的上次一次视觉改版是在2006年,但是我们得回溯到2000千禧年才有如此规模的从底层的重构和改版。我们决定重构用户端和服务端以支持我们新的服务、设计和新闻报道,比如说更佳的网站性能、响应式布局等等。尽管有些旧有的代码依旧保留或者进行了深度重构,大部分老的代码都被删除或者仅仅是用来做参考。\u003c/p\u003e\n\u003ch4 id=\"静态页面发布历史的教训\"\u003e\u003cstrong\u003e静态页面发布:历史的教训\u003c/strong\u003e\u003c/h4\u003e\n\u003cp\u003e直到今天为止,纽约时报的大部分网页内容还是静态 html 页面,这些页面储存在我们 …\u003c/p\u003e"
December 23, 2013
git stash和git stash pop的用法
"\u003cp\u003e推荐阅读: \u003ca href=\"http://www.cppblog.com/deercoder/archive/2011/11/13/160007.html\"\u003ehttp://www.cppblog.com/deercoder/archive/2011/11/13/160007.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e原文: \u003ca href=\"http://gitbook.liuhui998.com/4_5.html\"\u003ehttp://gitbook.liuhui998.com/4_5.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e一、基本操作\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e当你正在做一项复杂的工作时, 发现了一个和当前工作不相关但是又很讨厌的bug. 你这时想先修复bug再做手头的工作, 那么就可以用 git stash 来保存当前的工作状态, 等你修复完bug后,执行’反储藏\u0026rsquo;(unstash)操作就可以回到之前的工作里.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e$ git stash save \u0026#34;work in progress for foo feature\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e上面这条命令会保存你的本地修改到储藏(stash)中, 然后将你的工作目录和索引里的内容全部重置, 回到你当前所在分支的上次提交时的状态.\u003c/p\u003e\n\u003cp\u003e好了, 你现在就可以开始你的修复工作了.\u003c/p\u003e\n\u003cp\u003e… edit and test …\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e$ git commit -a -m \u0026#34;blorpl: typofix\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e当你修复完bug后, 你可以用git stash apply来回 …\u003c/p\u003e"
December 14, 2013
Nginx利用多核cpu提高性能_配置参数worker_cpu_affinity
"\u003cp\u003e上篇文章我们介绍了Nginx 的优化方法,这里主要对worker_cpu_affinity参数详细介绍一下.(官方\u003ca href=\"http://nginx.org/en/docs/ngx_core_module.html#worker_cpu_affinity\"\u003ehttp://nginx.org/en/docs/ngx_core_module.html#worker_cpu_affinity\u003c/a\u003e )\n\u003ca href=\"#\" title=\"收起\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"简介\"\u003e简介\u003c/h2\u003e\n\u003cp\u003eNginx默认没有开启利用多核cpu,我们可以通过增加worker_cpu_affinity配置参数来充分利用多核cpu的性能。cpu是任务处理,计算最关键的资源,cpu核越多,性能就越好。\u003c/p\u003e\n\u003ch2 id=\"规则设定\"\u003e规则设定\u003c/h2\u003e\n\u003cp\u003e(1)cpu有多少个核,就有几位数,1代表内核开启,0代表内核关闭\u003c/p\u003e\n\u003cp\u003e(2)worker_processes最多开启8个,8个以上性能就不会再提升了,而且稳定性会变的更低,因此8个进程够用了\u003c/p\u003e\n\u003ch2 id=\"演示实例\"\u003e演示实例\u003c/h2\u003e\n\u003ch3 id=\"两核cpu开启两个进程\"\u003e\u003cstrong\u003e两核cpu,开启两个进程\u003c/strong\u003e\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\nworker_processes 2;\nworker_cpu_affinity 01 10;\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e01表示启用了第一个cpu内核,10表示启用了第二个cpu内核\u003c/p\u003e\n\u003cp\u003eworker_cpu_affinity 01 10;表示开启了两个进程,第一个进程对应着第一个cpu内核,第二个进程对应着第二个cpu内核\u003c/p\u003e\n\u003ch3 id=\"两核cpu开启八个进程\"\u003e\u003cstrong\u003e两 …\u003c/strong\u003e\u003c/h3\u003e"
November 22, 2013
redmine与git组合配置
"\u003cp\u003e参考:\u003ca href=\"http://www.redmine.org/projects/redmine/wiki/HowTo_Easily_integrate_a_(SSH_secured)_GIT_repository_into_redmine\"\u003ehttp://www.redmine.org/projects/redmine/wiki/HowTo_Easily_integrate_a_(SSH_secured)_GIT_repository_into_redmine\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e在redmine 的”配置”选项里,填写git仓库位置的时候,一定要在写完整的.git路径,如 \u003cstrong\u003e/data/www/redmine/repos/agent/.git\u003c/strong\u003e ,否则redmine会无法发现git仓库.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://http://blog.haohtml.com/wp-content/uploads/2013/11/redmine-git-repo.png\"\u003e\u003cimg src=\"https://blogstatic.haohtml.com//uploads/2023/09/redmine-git-repo.png\" alt=\"redmine-git-repo\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e相关文章:\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://blog.csdn.net/benkaoya/article/details/8762935\"\u003ehttp://blog.csdn.net/benkaoya/article/details/8762935\u003c/a\u003e\u003c/p\u003e"
November 19, 2013
linux下使用iostat和pidstat查看进程使用资源情况
"\u003cp\u003e\u003cstrong\u003e引言\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e在查看系统资源使用情况时,很多工具为我们提供了从设备角度查看的方法。例如使用 \u003ca href=\"http://www.cnblogs.com/bangerlee/articles/2547161.html\"\u003eiostat\u003c/a\u003e 查看磁盘io统计信息:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003elinux:~ # iostat -d 3\nDevice: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn\nsda 1.67 0.00 40.00 120\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e以上显示的是从sda的角度统计的结果。当我们需要从进程的角度,查看每个进程使用系统资源的情况,有什么方法吗?\u003c/p\u003e\n\u003cp\u003e使用pidstat工具可以获取每个进程使用cpu、内存和磁盘等系统资源的统计信息,pidstat由sysstat rpm包提供,可在suse11使用。下面我们来看pidstat的具体用法。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e默认输出\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e执行pidstat,将输出系统启动后所有活动进程的cpu统计信息:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003elinux:~ # pidstat\nLinux 2.6.32.12-0.7-default (linux) 06/18/12 …\u003c/code\u003e\u003c/pre\u003e"
November 14, 2013
sysctl -P 报错 error: “net.bridge.bridge-nf-call-arptables” is an unknown key 的解决办法
"\u003cp\u003e今天在安装openvz的时候(安装教程: \u003ca href=\"/archives/14724\"\u003ehttp://blog.haohtml.com/archives/14724\u003c/a\u003e),修改完内核参数后,执行\u003c/p\u003e\n\u003cp\u003e[shell]sysctl -P[/shell]\u003c/p\u003e\n\u003cp\u003e后,提示\u003c/p\u003e\n\u003cp\u003e[shell]net.ipv4.ip_forward = 1\nnet.ipv4.conf.default.rp_filter = 1\nnet.ipv4.conf.default.accept_source_route = 0\nkernel.sysrq = 1\nkernel.core_uses_pid = 1\nnet.ipv4.tcp_syncookies = 1\nerror: \u0026ldquo;net.bridge.bridge-nf-call-ip6tables\u0026rdquo; is an unknown key\nerror: \u0026ldquo;net.bridge.bridge-nf-call-iptables\u0026rdquo; is an unknown key\nerror: \u0026ldquo;net.bridge.bridge-nf-call-arptables\u0026rdquo; is an …\u003c/p\u003e"
November 12, 2013
使用Vagrant在Windows下部署开发环境[转]
"\u003cp\u003e做Web开发少不了要在本地搭建好开发环境,虽然说目前各种脚本都有对应的Windows版,甚至是一键安装包,但很多时候和Windows环境的相性并不是那么好,各麻烦的问题是实际部署的环境通常是Linux,常常还要面临着开发和部署环境不一致,上线前还要大量的调试。更要命的是,如果有很多机器需要装的话,那就真是一个灾难了。\u003c/p\u003e\n\u003cp\u003eWindows下玩Linux少不了虚拟机,但装系统依旧是相当费事。在现在什么都在自动化的今天,Vagrant就是这么一个神器,基于Ruby开发,使用开源 \u003ca href=\"https://www.virtualbox.org/\"\u003eVirtualBox\u003c/a\u003e 作为虚拟化支持,可以轻松的跨平台部署。\u003c/p\u003e\n\u003cp\u003e今天试着把几台机器的环境都换成Vagrant,很爽很顺畅,于是就试着整理了一下使用小结:\u003c/p\u003e\n\u003cp\u003e目前所选用的是当前的最新版本Vagrant 1.2.7 (对应的Vagrantfile V2版),VirtualBox 使用的是 4.2.16\n准备工作:\u003c/p\u003e\n\u003cp\u003e下载安装 VirtualBox : \u003ca href=\"https://www.virtualbox.org/\"\u003ehttps://www.virtualbox.org/\u003c/a\u003e 下载安装 Vagrant : \u003ca href=\"http://www.vagrantup.com/\"\u003ehttp://www.vagrantup.com/\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e下载需要使用的 box :\u003c/p\u003e\n\u003cp\u003e官方提供的范例: …\u003c/p\u003e"
November 11, 2013
使用 Vagrant 打造跨平台开发环境
"\u003cp\u003e\u003ca href=\"http://vagrantup.com/\"\u003eVagrant\u003c/a\u003e 是一款用来构建虚拟开发环境的工具,非常适合 php/python/ruby/java 这类语言开发 web 应用,“代码在我机子上运行没有问题”这种说辞将成为历史。\u003c/p\u003e\n\u003cp\u003e我们可以通过 Vagrant 封装一个 Linux 的开发环境,分发给团队成员。成员可以在自己喜欢的桌面系统(Mac/Windows/Linux)上开发程序,代码却能统一在封装好的环境里运行,非常霸气。\u003c/p\u003e\n\u003ch2 id=\"安装步骤\"\u003e安装步骤\u003c/h2\u003e\n\u003ch3 id=\"1-安装-virtualbox\"\u003e1. 安装 VirtualBox\u003c/h3\u003e\n\u003cp\u003e虚拟机还是得依靠 VirtualBox 来搭建,免费小巧。\n下载地址: \u003ca href=\"https://www.virtualbox.org/wiki/Downloads\"\u003ehttps://www.virtualbox.org/wiki/Downloads\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cem\u003e* 虽然 Vagrant 也支持 VMware,不过 VMware 是收费的,对应的 Vagrant 版本也是收费的\u003c/em\u003e\u003c/p\u003e\n\u003ch3 id=\"2-安装-vagrant\"\u003e2. 安装 Vagrant\u003c/h3\u003e\n\u003cp\u003e下载地址: \u003ca href=\"http://downloads.vagrantup.com/\"\u003ehttp://downloads.vagrantup.com/\u003c/a\u003e 根据提示一步步安装。\u003c/p\u003e\n\u003cp\u003e此外,还得下载官方封装好的基础镜像:\nUbuntu precise 32 VirtualBox …\u003c/p\u003e"
November 9, 2013
lxc学习-安装篇
"\u003cp\u003e\u003cstrong\u003e安装环境:\u003c/strong\u003e\u003c/p\u003e\n\u003ch1 id=\"内存-1g\"\u003eVirtualBox 4.2.18\nCentos6.4 64位\n内存 1G\u003c/h1\u003e\n\u003cp\u003e\u003cstrong\u003e安装方法:\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e[shell]\u003c/p\u003e\n\u003cp\u003eyum -y install gcc libcap-devel libcgroup\nwget \u0026ldquo;\u003ca href=\"http://downloads.sourceforge.net/project/lxc/lxc/lxc-0.9.0/lxc-0.9.0.tar.gz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Flxc%2Ffiles%2Flxc%2F\u0026amp;ts=1383981486\u0026amp;use_mirror=jaist%22\"\u003ehttp://downloads.sourceforge.net/project/lxc/lxc/lxc-0.9.0/lxc-0.9.0.tar.gz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Flxc%2Ffiles%2Flxc%2F\u0026amp;ts=1383981486\u0026amp;use_mirror=jaist\u0026quot;\u003c/a\u003e\ntar zxvf lxc-0.9.0.tar.gz\ncd lxc-0.9.0\n./autogen.sh\n./configure\nmake \u0026amp;\u0026amp; make install[/shell]\u003c/p\u003e\n\u003cp\u003e这里,在/usr/local/bin 目录里可以看到以 lxc_开头的命令.(注意要将这个目录添加到用户的环境变量里)\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://blog.haohtml.com/wp-content/uploads/2013/11/lxc_commends.png\"\u003e\u003cimg src=\"http://blog.haohtml.com/wp-content/uploads/2013/11/lxc_commends.png\" alt=\"lxc_commends\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e更多学习参考资料请参考: …\u003c/p\u003e"
November 4, 2013
PHP 多台服务器 session 用Memcached存储Session
"\u003cp\u003e\u003cstrong\u003ephp实现多服务器共享session的方法:\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e多服务器共享session的方法:\u003c/p\u003e\n\u003cp\u003e1.通过NFS文件共享的方式,多台WEB服务器共享保存session文件的磁盘\n2.保存在数据库中,这种方式的扩展性很强,可以随意增加WEB而不受影响\n3.可以将session数据保存在memcached中,memcached是基于内存存储数据的,性能很高,用户并发量很大的时候尤其合适,参考PHP实现多服务器session共享之memcache共享\n4.文件方式保存session时,可以采用php的扩展eaccelerator来存储sesion\u003c/p\u003e\n\u003cp\u003ephp中的Session默认是用文件的方式存储的,如果用多台WEB服务器,Session共享可能就会成为一个大的问题,可以用NFS共享的方式来存储,但是对于并发请求更多的站点来说,用NFS也会出现问题,下面就说说用Memcached来保存Session的问题。\u003c/p\u003e\n\u003cp\u003evi memcached_session.php,输入如下的代码\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e$ip = \u0026#39;192.168.1.111\u0026#39;;\n$port = 11211; …\u003c/code\u003e\u003c/pre\u003e"
October 31, 2013
Golang import使用说明
"\u003cp\u003e我们在写Go代码的时候经常用到import这个命令用来导入包文件,而我们经常看到的方式参考如下:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\nimport(\n\u0026#34;fmt\u0026#34;\n)\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e然后我们代码里面可以通过如下的方式调用\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003efmt.Println(\u0026#34;hello world\u0026#34;)\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e上面这个fmt是Go语言的标准库,他其实是去goroot下去加载该模块,当然Go的import还支持如下两种方式来加载自己写的模块:\u003c/p\u003e\n\u003cp\u003e1.相对路径\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eimport “./model” //当前文件同一目录的model目录,但是不建议这种方式来import\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e2.绝对路径\u003c/p\u003e\n\u003cp\u003eimport “shorturl/model” //加载gopath/src/shorturl/model模块\u003c/p\u003e\n\u003cp\u003e上面展示了一些import常用的几种方式,但是还有一些特殊的import,让很多新手很费解,下面我们来一一讲解一下到底是怎么一回事\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e1.点操作\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e我们有时候会看到如下的方式导入包\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eimport(\n. \u0026#34;fmt\u0026#34;\n)\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e这个点操作的含义就是这个包导入之后在你调用这个包的函数时,你可以省略前缀的包名,也就是前面你调用 …\u003c/p\u003e"
October 22, 2013
安装zeromq时,出现 error while loading shared libraries: libzmq.so 错误的解决办法
"\u003cp\u003eIs this on Ubuntu? You’ll need to add /usr/local/lib to ldconfig to be able to use ZeroMQ. Here’s a web page with some info: \u003ca href=\"http://ubuntuforums.org/showthread.php?t=420008\"\u003ehttp://ubuntuforums.org/showthread.php?t=420008\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eHere are the actual instructions:\u003c/p\u003e\n\u003cp\u003eAdd \u003cstrong\u003e/usr/local/lib\u003c/strong\u003e to a new line in ld.so.conf:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e$ sudo vi /etc/ld.so.conf\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eRerun ldconfig:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e$ sudo ldconfig\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThat should work (if I remember correctly). Let me know if you have any issues.\u003c/p\u003e"
October 22, 2013
golang实现验证电子信箱和手机格式合法性(正则表达式)
"\u003cp\u003e邮箱验证\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003efunc checkEmail(email string) (b bool) {\n if m, _ := regexp.MatchString(\u0026#34;^([a-zA-Z0-9\\_-])+@([a-zA-Z0-9\\_-])+(.[a-zA-Z0-9_-])+\u0026#34;, email); !m {\n \treturn false\n }\n return true\n}\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e手机验证\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003epackage main\nimport (\n\u0026#34;regexp\u0026#34;\n)\n\nconst (\n\tregular = \u0026#34;^(13[0-9]|14[57]|15[0-35-9]|18[07-9])\\\\d{8}$\u0026#34;\n)\n\nfunc validate(mobileNum string) bool {\n reg := regexp.MustCompile(regular)\n return reg.MatchString(mobileNum)\n}\n\nfunc main() {\n if validate(\u0026#34;13888888888\u0026#34;) { …\u003c/code\u003e\u003c/pre\u003e"
October 22, 2013
[必读]golang语言报错信息fatal error: all goroutines are asleep – deadlock!
"\u003cp\u003e出错信息\u003cstrong\u003efatal error: all goroutines are asleep – deadlock!\u003c/strong\u003e\n\u003cstrong\u003e出错信息的意思是:\u003c/strong\u003e\n在main goroutine线,期望从管道中获得一个数据,\u003cstrong\u003e而这个数据必须是其他goroutine线放入管道的\u003c/strong\u003e\n但是其他goroutine线都已经执行完了(all goroutines are asleep),那么就永远不会有数据放入管道。\n所以,main goroutine线在等一个永远不会来的数据,那整个程序就永远等下去了。\n这显然是没有结果的,所以这个程序就说“算了吧,不坚持了,我自己自杀掉,报一个错给代码作者,我被deadlock了”\n例子:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003epackage main\n\nfunc main() {\n c := make(chan bool)\n go func() {\n c \u0026lt;- true\n }()\n \u0026lt;-c //这里从c管道,取到一个true\n \u0026lt;-c //这行导致deadlock,因为这时的c管道,永远都取不到数据(注释掉这行就不报错)\n}\n\u003c/code\u003e\u003c/pre\u003e"
October 22, 2013
golang日志模块测试
"\u003cpre tabindex=\"0\"\u003e\u003ccode\u003epackage main\n\nimport (\n \u0026#34;fmt\u0026#34;\n \u0026#34;log\u0026#34;\n \u0026#34;os\u0026#34;\n)\n\nfunc main(){\n logfile,err := os.OpenFile(\u0026#34;d:/workspace/golang/test.log\u0026#34;,os.O\\_RDWR|os.O\\_CREATE|os.O_APPEND,0);\n if err!=nil {\n fmt.Printf(\u0026#34;%s\\r\\n\u0026#34;,err.Error());\n os.Exit(-1);\n }\n defer logfile.Close();\n \n logger := log.New(logfile,\u0026#34;\\r\\n\u0026#34;,log.Ldate|log.Ltime|log.Llongfile);\n logger.Println(\u0026#34;hello\u0026#34;);\n logger.Println(\u0026#34;oh….\u0026#34;);\n logger.Fatal(\u0026#34;test\u0026#34;); …\u003c/code\u003e\u003c/pre\u003e"